2018-05-29

Intel计算棒更新到Windows 10 1803后WIFI问题解决方法

Intel计算棒(Atom Z3735F@1.33GHz)更新Windows 10 1803后,WIFI连不上,能连上时速度特别慢,一会又断了。
查看网卡是RTL8723BS,Windows提供的驱动是2017年11月的,去realtek官方网站更新驱动到2017年6月,无效。
后来发现先打开飞行模式再打开WIFI即可正常,此时飞行模式和WIFI同时处于打开状态。

可能需要把蓝牙关掉,因为有人反映说这个IC的WIFI和蓝牙会互相干扰。

2014-04-13

使用ACM Java Task Force包时的DLL错

Windows 7 64位环境使用ACM Java Task Force时出错:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\user\GCMDLN.DLL: Can't load IA 32-bit .dll on a AMD 64-bit platform
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(Unknown Source)
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.load0(Unknown Source)
        at java.lang.System.load(Unknown Source)
        at acm.util.DOSCommandLine.getCommandLine(JTFTools.java:1622)
        at acm.util.JTFTools.getCommandLine(JTFTools.java:439)
        at acm.util.JTFTools.getMainClass(JTFTools.java:464)
        at acm.program.Program.main(Program.java:1320)

原因是ACM Java Task Force库不鼓励用户自己写main方法,在acm.program.Program和acm.program.CommandLineProgram的main方法中通过猜测方式获取实际要执行的类,main中用到的acm.util.DOSCommandLine里包含的GCMDLN.DLL是32位的(转为字符串形式存在代码中并在需要时解到user.home目录),需要做64位DLL来实现getLine方法。

先用javah生成头文件
javah -d . -classpath acm.jar acm.util.DOSCommandLine
比较了一下,32位和64位JRE生成的头文件是一样的。

再根据头文件写代码
从对返回值的使用上来看,直接获取调java时的命令行即可。
JNIEXPORT jstring JNICALL Java_acm_util_DOSCommandLine_getLine(JNIEnv *env, jclass cl)
{
    LPWSTR s = GetCommandLineW();
    return (*env)->NewString(env, s, lstrlenW(s));
}

用tcc编译
tcc -I"C:\Program Files\Java\jdk1.8.0\include" -I"C:\Program Files\Java\jdk1.8.0\include\win32" -shared -o GCMDLN.DLL.DLL acm_util_DOSCommandLine.c
放在System32下就可以了。

为什么输出成GCMDLN.DLL.DLL?
因为acm.util.DOSCommandLine里写的是System.loadLibrary("GCMDLN.DLL"),库名带了后缀,以前的JRE这么写可能没问题,现在不行了。现在的32位JRE里跑jtf库也会报错:
Exception in thread "main" java.lang.UnsatisfiedLinkError: acm.util.DOSCommandLine.getLine()Ljava/lang/String;
        at acm.util.DOSCommandLine.getLine(Native Method)
        at acm.util.DOSCommandLine.getCommandLine(JTFTools.java:1627)
        at acm.util.JTFTools.getCommandLine(JTFTools.java:439)
        at acm.util.JTFTools.getMainClass(JTFTools.java:464)
        at acm.program.Program.main(Program.java:1320)

于是也做了32位的DLL放在SysWOW64下,这样就不用考虑JRE位数了。

代码和DLL放在了My Shared Folder里的jtf-GCMDLN.zip。

不用DLL的解决方法:
  1. 打成jar在minifest里指定类名;
  2. 自己写main方法;
  3. 在命令行加上“code=类名或class文件路径”的参数指定类名。

2013-09-26

如何搭建本地pypi服务器

如果是建pypi镜像,直接用pypimirror就行了。但这次是要提供一些经过检查的包(可能有C语言扩展,需要人工检查确保没有安全问题)供内网机器用easy_install安装。

1. 生成安装包
解开源码包,运行:
python setup.py bdist_egg
在dist目录下会生成egg。

有的库会报错,因为zip_safe是在setuptools里定义的,而库的setup.py里写的还是distutils,将from distutils.core import setup改成from setuptools import setup即可。

2. 提供服务
https://pypi.python.org/pypi/pypiserver 用起来最简单,下载一个文件就行:
wget --no-check-certificate https://raw.github.com/schmir/pypiserver/standalone/pypi-server-standalone.py

把上一步生成的egg都放到某个目录里,比如/root/pypi/packages,然后启动服务:
python pypi-server-standalone.py --disable-fallback --server twisted --root /root/pypi/packages --port 4321
--disable-fallback 表示本地缺包时不转到官方的pypi;
--server 指定使用twisted提供服务,因为我先前刚好装过,否则还得装waitress。

访问 http://server:4321/ 就能看到介绍了。

3. 使用
在~/.pydistutils.cfg中加入:
[easy_install]
index-url = http://server:4321/simple/

安装时使用:
/opt/apps/python/bin/easy_install package_name

如果在package_name的位置写url,就不用改配置文件。

2013-09-11

为什么emacs找不到java

从emacs的shell里运行java时,总是显示“'java' 不是内部或外部命令,也不是可运行的程序或批处理文件。”
原因:被WoW64把对C:\Windows\System32的访问重定向到C:\Windows\SysWOW64了。

一开始没往这方面想,比较shell里和cmd中的环境变量发现不一致了才想起来。一搜才发现半年前就有人问过了

2013-02-26

用ld和LD_PRELOAD替换调用的函数

以前虽然也知道应该怎么把程序中用到的函数替换掉,但还从来没有实际做过,最近因工作需要才动手做了一遍。

写一个最简单的hello world程序

// main.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    puts("Hello World!");
    return 0;
}
// end of main.c

# gcc main.c -o 1
# ./1
Hello World!

1. 静态编译
使用ld的命令行参数--wrap,a,表示对a的调用改为对__wrap_a的调用,而对__real_a的调用改为对原来的a的调用。

// stub.c
int __wrap_puts(const char *s)
{
    int result;
    __real_puts("========before real call========");
    result = __real_puts(s);
    __real_puts("======== after real call========");
    return result;
}
// end of stub.c

# gcc -Wl,--wrap,puts main.c stub.c -o 2
# ./2
========before real call========
Hello World!
======== after real call========

2. 动态编译
使用LD_PRELOAD,然后用dlsym取原来的符号地址,缺点是由于安全原因对有suid或sgid的程序没法用,据说有的系统调用也没法这么拦截,需要用ptrace。

// dynstub.c
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>

int puts(const char *s)
{
    int result;
    static typeof(puts) *orig_puts = NULL;
    if (orig_puts == NULL)
        orig_puts = dlsym(RTLD_NEXT, "puts");
    (*orig_puts)("========before real call========");
    result = (*orig_puts)(s);
    (*orig_puts)("======== after real call========");
    return result;
}
// end of dynstub.c

# gcc -fpic -shared -ldl -o dynstub.so dynstub.c
# LD_PRELOAD=/root/tmp/dynstub.so ./1
========before real call========
Hello World!
======== after real call========

在每个函数里用dlsym看起来也不太美观,可能__attribute__ ((constructor))更好点,但这就是大量使用的时候才需要考虑的问题了。

// dynstub2.c
#define _GNU_SOURCE
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>

static typeof(puts) *orig_puts = NULL;

__attribute__ ((constructor)) void loadsym()
{
    orig_puts = dlsym(RTLD_NEXT, "puts");
    assert(orig_puts != NULL);
}

int puts(const char *s)
{
    int result;
    (*orig_puts)("========before real call========");
    result = (*orig_puts)(s);
    (*orig_puts)("======== after real call========");
    return result;
}
// end of dynstub2.c

2012-03-11

开始尝试J2ME和Eclipse

以前做Java都是给现成项目添功能或改bug,直接在服务器上vim写完再ant就成,年初换了个对J2ME支持好点的手机,一直想写点啥试试,今天才有了时间。

安装Eclipse的时候与网上文章有些不一样,EclipseME早就变成了Eclipse Mobile Tools for Java,安装起来不需要用eclipseme.feature_1.7.9_site.zip了。

步骤记一下:
  1. 安装jdk-7u3-windows-i586.exe和oracle_java_me_sdk-3_0_5.exe;
  2. 下载eclipse-java-indigo-SR2-win32.zip,解压到安装目录并启动;
  3. 选择Help->Install New Software,在“Work with”里选择“--All Available Sites--”,下面列表框点开“Mobile and Device Development”,选中“Mobile Tools for Java”、“Mobile Tools for Java Examples”和“Mobile Tools for Java SDK”,然后一路点Next安装完后重启eclipse;
  4. 选择Window->Preferences,左边列表选择“Java ME”,右边WTK Root选择oracle_java_me_sdk-3_0_5.exe安装到的目录,左边列表选择“Java ME”下面的“Device Management”,右边选择“Manual Install”,同样选择上一步的目录,扫描完毕后选择缺省模拟器,DefaultCldcPhone1比ClamshellCldcPhone1界面简单点。因为目前也就是玩玩,不做与具体手机类型结合紧密的东西,Nokia模拟器或Motorola模拟器之类的不需要装。
  5. 在File->New里先创建Midlet Project再创建Java ME MIDlet,写完代码直接运行就会启动模拟器了。