记系统函数报错原因定位方法

前言

本文描述一个问题的常用定位方法以及如何解决。运行的环境为在linux4.19内核版本下运行一个app代码发现系统调用报错。特用此文记录该问题的解决思路。

问题描述

简单写一个epoll相关的测试代码

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/epoll.h>

int main(void)
{
    
    
        int fd = -1;

        fd = epoll_create1 (EPOLL_CLOEXEC);
        if(fd < 0) {
    
    
                printf("ret:%d,%d[%s]\n", fd, errno, strerror(errno));
                perror("abd2233");
        }
        printf("ret:%d\n", fd);
        while(1)
        {
    
    
                sleep(1);
        }
        return 0;
}

1.编译生成epoll的可执行程序
2.运行如下报错,表示函数不可达。

/mnt/nfs #
/mnt/nfs # ./epoll
ret:-1,38[Function not implemented]
abd2233: Function not implemented
ret:-1
在这里插入图片描述

分析

1.由于该函数是系统调用函数,那么其调用一定是通过c库调用。那么首先就要看c库里面是否有其代码的实现
/mnt/nfs # grep -rn “epoll_create1” /lib/libc.so.1
25108:epoll_create1
/mnt/nfs #
在这里插入图片描述
2.假如c库没有实现那么就需要更换更高版本的c库或者工具链
3.明明c库有实现,却提示函数为实现,那么有可能是系统调用出了问题,继续往下挖掘
4.既然怀疑系统调用出了问题,那么就需要大致了解下系统调用的过程。

系统调用

系统调用表

1.可以尝试在编译工具链目录下寻找下系统调用表如下图所示。
arm-ca9-linux-uclibcgnueabihf-8.4.01\share\gdb\syscalls
在这里插入图片描述
在这里插入图片描述
2.也可以在内核目录下./arch/arm/目录下搜索系统调用函数 也能收到表
grep -Rn ‘epoll_create1’ ./arch/arm/

3.我们知道系统调用是通过系统调用号来进行匹配对应执行的(由app切入内核)。发现epoll_create1的系统调用号 357 号码对上没看到实体定义,同时定义了宏__NR_epoll_create1
在这里插入图片描述
4.系统调用相关的函数在./include/uapi/ 一定有线索,再次搜索grep -Rn ‘__NR_epoll_create1’ ./include/uapi/

在这里插入图片描述

SYSCALL_DEFINE1(epoll_create1, int, flags)在这里插入图片描述

5.发现有一个__SYSCALL就是系统调用的定义,参数前面是号码后面是实现实体
到这个文件里面去看 它的实体是sys_epoll_create1 且有提示在/* fs/eventpoll.c */中实现
在这里插入图片描述
6.去eventpoll.c文件下查看,但是在 fs/eventpoll.c中并没有发现sys_epoll_create1函数实现
去kernel目录下搜索实体
grep -Rn ‘sys_epoll_create1’ ./kernel/
发现只有.o有,说明很有可能是宏拼接的
在这里插入图片描述
7.查看该文件果然,同时也有提示我们去fs/eventpoll.c查看,说明
sys_epoll_create1的实现在fs/eventpoll.c 的epoll_create1函数。
在这里插入图片描述
在这里插入图片描述
同时在eventpoll.c中,这个SYSCALL_DEFINE1展开就是定义
sys_epoll_create1在这里插入图片描述在这里插入图片描述

编译

1.查看是否编译进内核,去fs/eventpoll.c 目录查看发现没有相对应的.o文件,发现没有编译
在这里插入图片描述
2.查看makefile,该文件编译需要这个宏CONFIG_EPOLL
在这里插入图片描述
3.查看.config 确实没有定义
在这里插入图片描述
4.打开内核配置将相对应的内核配置上即可

结论

系统调用报错无非在两个地方有可能出错,那便是c库没有实现该系统调用以及内核不支持该系统调用

解决方法:1.确定c库有该系统调用的实体,2.修改内核配置文件从新编译该内核使其支持该系统调用。

Guess you like

Origin blog.csdn.net/weixin_41884251/article/details/115699160