自定义Linux系统调用sys_set_weight传负值返回0而非-EINVAL问题
问题原因分析
以下是导致该异常的几个常见原因:
- 未重启进入新编译的内核
修改内核添加系统调用后,必须编译安装新内核并重启进入该内核才能生效。如果仍运行原有内核,334号系统调用可能对应其他逻辑或空实现,刚好返回0,不会触发你编写的负值校验逻辑。 - 32位用户态运行在64位内核上的符号扩展问题
你在64位内核中定义的系统调用参数是long(64位有符号数),如果测试代码被编译为32位程序,传入的int类型-3传递到64位内核时如果没有正确做符号扩展,会被识别为正数4294967293,导致weight < 0的校验不成立,直接返回0。
可以执行file 测试程序名确认测试程序位数,如果是32位,编译时添加-m64参数生成64位程序即可验证。 - 测试代码未正确包含syscall相关头文件
如果用户态测试代码没有包含<unistd.h>、<sys/syscall.h>头文件,C语言会对syscall函数做隐式声明,默认返回值为int、参数类型按默认规则提升,可能导致参数传递异常,-3没有被正确传入内核。 - 内核编译配置问题
你添加的系统调用实现代码没有被正确编译进内核镜像,比如源文件没有添加到对应Makefile中,导致实际运行的内核中该系统调用逻辑不是你编写的版本。
排查建议
- 首先执行
uname -a确认当前运行的内核版本是否为你修改后的版本 - 在系统调用实现中添加
printk打印传入的weight值,通过dmesg查看内核日志确认参数是否正确传入 - 显式将传入syscall的参数强转为
long类型:long r = syscall(334, (long)weight);,排除类型转换问题
内容的提问来源于stack exchange,提问作者user15874403
相关产品推荐
相关产品推荐

