当系统调用不存在……
具体的问题抽象出来就是这么一种情况:
有一堆分层的目录,里面全是系统调用的相关测试代码+Makefile,结构大致如下:
├── wait4
│ ├── Makefile
│ ├── wait401.c
│ └── wait402.c
├── waitid
│ ├── waitid01
│ │ ├── Makefile
│ │ └── waitid01.c
│ ├── waitid02
│ │ ├── Makefile
│ │ └── waitid02.c
├── waitpid
│ │ ├── Makefile
│ │ └── waitpid_err_test.c
.....
现在要把这堆系统调用的测试代码移植到各硬件平台和各发行版上,因此要考虑内核版本、glibc版本等等问题。比如说getcpu这个东东只在2.6.19及以后版本中存在并且只有x86_64 and i386架构才可用。而编译这堆系统调用使用的Makefile大致如下:
1 2 3 4 5 | MAKEFILES_FOR_TESTCASES = $(shell find testcases -name Makefile) TESTCASES_BY_MAKE = $(addsuffix /test,$(dir $(MAKEFILES_FOR_TESTCASES))) $(TESTCASES_BY_MAKE): $(MAKE) -C $(dir $@) test |
因此可能的解决方案有如下几种:
1. 修改Makefile,禁止编译会出错的测试用例
1 2 3 4 5 6 7 8 | FILTER_OUT_CASES = testcase1 testcase2 testcase3 ALL_MAKEFILES = $(shell find testcases -name Makefile) FILTER_OUT_MAKEFILES = $(wildcard $(foreach filename,$(FILTER_OUT_CASES),testcases/$(filename)/Makefile)) MAKEFILES_FOR_TESTCASES = $(filter-out $(FILTER_OUT_MAKEFILES),$(ALL_MAKEFILES)) TESTCASES_BY_MAKE = $(addsuffix /test,$(dir $(MAKEFILES_FOR_TESTCASES))) $(TESTCASES_BY_MAKE): $(MAKE) -C $(dir $@) test |
代码很平淡无奇,之所以贴出这段代码是为了温习一下Makefile中wildcard,filter-out和foreach的用法
2.修改c代码,使用预处理判断是否存在
这种办法在ltp上应用十分广泛,ltp中自动从configure文件中生成include/config.h,生成的config.h包含了一系列预处理,例如:
1 2 3 4 5 | /* Define to 1 if you have the <sys/signalfd.h> header file. */ #undef HAVE_SYS_SIGNALFD_H /* Define to 1 if you have the <sys/stat.h> header file. */ #define HAVE_SYS_STAT_H 1 |
当内核版本不同导致系统调用不存在时,可以设置undef预处理;如果系统调用存在,则define一下。
接下去可以修改源代码,在可能会在不同内核版本上出现分歧的代码前后加上:
1 2 3 4 5 6 7 8 9 | #ifdef HAVE_SYS_SIGNALFD_H ... #else int main() { printf("syscall not exists in this platform\"); return 1; } #endif |
同时ltp还在C代码中判断内核版本,内核版本在
如果不使用configure文件,可以自己写一个shell脚本来生成,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/sh CONFIG_PATH=./include/config.h KVER=`uname -r | cut -d'-' -f 1` KMAJVER=`echo $KVER | cut -d'.' -f 1-2` KMINVER=`echo $KVER | cut -d'.' -f 3` if [ "$KMAJVER" = "2.6" ] && [ $KMINVER -ge 19 ]; then echo '#define HAVE_SYS_EPOLL_H 1' >> $CONFIG_PATH else echo '#ifdef HAVE_SYS_EPOLL_H' >> $CONFIG_PATH echo '# undef HAVE_SYS_EPOLL_H' >> $CONFIG_PATH echo '#endif' >> $CONFIG_PATH fi |
