下文转自:http://qiuhanstar.blog.163.com/blog/static/3085469520091178444664/
Linux Device Driver3提供的setlevel.c在2.6.20内核上编译通不过,在编译时提示:expected declaration specifiers or ‘…’ before syslog
setlevel.c中的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* #include <unistd.h> */ /* conflicting on the alpha */
#define __LIBRARY__ /* _syscall3 and friends are on ly available through this */
#include <linux/unistd.h>
/* define the system call, to override the library function */
_syscall3(int, syslog, int, type, char *, bufp, int, len);
int main(int argc, char **argv)
{
int level;
if (argc==2) {
level = atoi(argv[1]); /* the chosen console */
} else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (syslog(8,NULL,level) < 0) {
fprintf(stderr,"%s: syslog(setlevel): %s\n",
argv[0],strerror(errno));
exit(1);
}
exit(0);
}
问题很显然出现在_syscall3上。
程序中_syscall3(int, syslog, int, type, char *, bufp, int, len)这条语句的作用是告诉编译器,需要的系统调用是syslog,返回值是int,而后面的字符串则是syslog需要的3个参数及其类型。
而setlevel.c之所以编译通不过,是因为Linux Device Driver3的作者是在2.6.10的Linux内核中写的这个程序,但是2.6.20的Linux内核中却并没有定义_syscall3这个函数。(我在Red Hat 9.0(2.4的内核)中编译过setlevel.c,可以正常通过。)
于是只要在setlevel.c中调用_syscall3之前定义它的原型,那么setlevel.c就可以正常编译和使用了。增加代码后的setlevel.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h> /*需要加上这个头文件,否则编译不能通过*/
#define __syscall_return(type, res) \
do { \
if ((unsigned long)(res) >= (unsigned long)(-125)) { \
errno = -(res); \
res = -1; \
} \
return (type) (res); \
} while (0)
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3))); \
__syscall_return(type,__res); \
}
_syscall3(int,syslog, int,type, char *,bufp, int,len);
int main(int argc, char **argv)
{
int level;
if (argc==2) {
level = atoi(argv[1]); /* the chosen console */
} else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (syslog(8,NULL,level) < 0) {
fprintf(stderr,"%s: syslog(setlevel): %s\n",
argv[0],strerror(errno));
exit(1);
}
exit(0);
}