linux系统调用及错误处理

2018-05-18 17:20:33

系统调用是内核提供给外部程序的接口,进程可以通过系统调用来一自己的名义来执行某些动作。在深入了解系统调用之前,先关注以下几点。
1.系统调用处理器会从用户态切换到核心态以便能访问到内存核心空间。
2.系统调用的组成是固定的,每个系统调用都有一个唯一的数字来标识,而程序只是通过名称来调用。

从编程角度来讲,它跟c语言函数的调用很像,但是系统调用会经历的步骤往往更多。

系统调用内部细节已超出了本文的范围,普通的linux编程只需要记住以下几点
1.普通的一次系统调用开销是一次普通c库函数调用的20倍以上,所以用c普通函数解决的绝不用系统调用。
2.系统调用内核还需验证系统调用参数,用户空间内存和内核控件内存的复制
3.系统调用后我们都必须检查下返回值以及全局变量errno来确定系统调用是否报错了。
4.在linux上如果想检查一个程序执行了哪些系统调用,可用strace命令。

系统调用错误处理

系统调用的手册里都有记录调用可能的返回值,并指出哪些返回值表示错误。通常返回值是-1表示出错。
系统调用失败时会将全局整型变量errno设置为一个正值来标识具体错误。头文件<errno.h>提供了对errno的声明以及一些跟错误码有关的常量定义。
系统调用和库函数调用成功errno不会被重置为0,因此我们不能直接来判断errno来确定错误,有可能是之前的函数失败造成的。因此在检查错误时,必须先判断返回值,如果出错再根据errno来确定具体错误。
少数系统调用(如getpriority())在调用成功后也会返回-1,要判断此类系统调用是否发生错误,应提前将errno置为0,然后调用后再对errno进行判断。

void perror(const char *msg);
此函数会打印出字符串msg紧跟与当前errno值对应的错误描述。

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
    int fd = open("aaa", O_WRONLY);
    if(fd == -1){
        perror("open");
    }
    
    return -1;
}
//open: No such file or directory


char *strerror(int errnum);
该函数会根据errnum错误号返回错误描述字符串,由于返回的字符串是静态分配的,这就意味着后续调用strerror()可能会覆盖之前的字符串,所以如果该错误描述后续还要用到,建议复制一个副本。

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

int main(){
    int fd = open("aaa", O_WRONLY);
    char *tmp = strerror(errno);
    printf("errno:%d, %s\n", errno,tmp);
    
    printf("errno:%d, %s\n", 3,strerror(3));
    printf("errno:%d, %s\n", 4,strerror(4));
}
/*
errno:2, No such file or directory
errno:3, No such process
errno:4, Interrupted system call
errno:1111, Unknown error 1111
*/

注意由于perror和strerror函数跟本地环境有关,所以如果你的linux是中文版的,则输出的字符串也会变成中文。


备注

1.本文对系统调用做了简单的介绍,如果有疑问可以给我留言
2.gcc4.8,运行环境centos7 64位
3.原文地址http://www.freecls.com/a/2712/29

©著作权归作者所有
收藏
推荐阅读
  • linux内核简介

    内核是用来管理和分配计算机资源的,它主要有进程调度、内存管理、提供文件系统、创建和终止进程、对设备的访问、联网、提供系统调用的接口等。内核还可以为内阁用户模拟出抽象的虚拟私有计算机,每个用户都可以登录...

  • linux centos7 安装逻辑卷指令来支持lvm2

    报如下错时。-bash: pvcreate: command not found-bash: pvscan: command not found-bash: pvdisplay: command no...

  • linux命令系列-fuser,lsof,pidof

    fuser 可以借由文件(或文件系统) 找出正在使用该文件的程序。有的时候我想要知道我的程序到底在这次启动过程中打开了多少文件,可以利用 fuser 来观察啦! 举例来说,你如果卸载时发现系统通知:“...

  • err
    linux利用ssh-keygen实现免密码登录

    思考下以下几个问题:利用crontab定时任务半夜利用sftp或rsync来自动链接远程来备份文件利用xshell或linux之间登录时无需重复输入密码即可直接登录我们知...

  • linux命令系列-ln(软硬链接)

    ln命令可以生成软链接和硬链接,也可叫做符号链接和实体链接。 有兴趣深入理解的可以查阅相关文档,一般的读者只需记住以下几点即可: 1.不管是软链接还是硬链接都不会额外增加磁盘空间(虽然实际情况可能会多...

  • nginx模块 ngx_http_headers_module

    ngx_http_headers_module 模块是用来增加 Expires 和 Cache-control,或者是任意的响应头。Syntax: add_header name value [alw...

  • nginx模块 ngx_http_gunzip_module、ngx_http_gzip_module、ngx_http_gzip_static_module

    ngx_http_gunzip_module 模块将文件解压缩后并在响应头加上 "Content-Encoding: gzip" 返回给客户端。为了解决客户端不支持gzip压缩。编译的时候带上 --w...

  • nginx模块 ngx_http_flv_module、ngx_http_mp4_module

    ngx_http_flv_module模块提供了对 flv 视频的伪流支持。编译的时候带上 --with-http_flv_module。它会根据指定的 start 参数来指定跳过多少字节,并在返回数...

  • nginx模块 ngx_http_fastcgi_module

    ngx_http_fastcgi_module 模块使得nginx可以与 fastcgi 服务器通信。比如目前要使得 nginx 支持 php 就得使用 fastcgi技术,在服务器上装上 nginx...

  • nginx模块 ngx_http_autoindex_module

    ngx_http_autoindex_module 模块可以将uri以 / 结尾时,列出里面的文件和目录。Syntax: autoindex on | off; Default: autoindex ...

简介
天降大任于斯人也,必先苦其心志。