几乎所有的系统函数和库函数在执行时都会通过返回特定的值来说明成功或出错。我们在调用它们后,必须马上对其返回值进行检测,如果调用出错则要进行相应的处理(一般是向终端输出错误信息并终止程序运行)。否则在今后程序出错时,如果通过调试去定位到该错误将会花费很长的时间。
当然也有某些系统调用从不失败(例如getpid()或_exit()等),在调用它们时可以不进行错误检测。
1.如何发现系统调用出错
- 每个系统调用的manual page都会详细介绍可能的返回值。通常,用“-1”来表示出错,因此出错检测语句可以这样写:
fd = open(pathname, flags, mode);
if(fd == -1){
/* code to handle the error */
}
...
if(close(fd) == -1){
/* code to handle the error */
}
当一个系统调用失败时,内核会根据错误类型将error设定一个特定的非负整数。头文件<error.h>
为每一个可能的error值定义了一个以“E”开头的宏名,在错误处理函数中可以通过检测这个特定的宏名来判断错误类型。
cnt = read(fd, buf, numtybes);
if(cnt == -1){
if(errno == EINTR)
fprintf(stderr, "read was interrupted by a signal
");
else{
/*some other error occurred */
}
}
当系统调用成功时,它并不会将error设定为0。因此,可能出现的一种情况是当前的系统函数成功执行了,但当前error值还是以前某次系统调用出错时设定的值,为此,在对error值进行检测以判定是哪种错误时,一定一定要先检查当前系统调用是否发生错误!
- 有些系统函数在出错时并非返回“-1”,甚至在执行成功时返回“-1”。这种情况下,我们可以在系统调用前先将error设为0,待系统调用结束后,通过判定error是否为0就可知错误是否发生。
2.如何处理系统调用出错
对待系统调用出错的常见处理方法是基于error值输出不同的错误提示消息。库函数perror()
和strerror()
提供类似的功能。
perror()
函数先打印由用户自定义的字符串后,接着输出error值对应的错误提示字符串。
#include <stdio.h>
void perror(const char *msg);
一个使用它的简单的例子:
fd = open(pathname, flags, mode);
if(fd == -1){
perror("open");
exit(EXIT_FAILURE);
}
strerror()
函数根据参数值返回特定的错误消息。
#include <string.h>
char *strerror(int errnum);
//返回与errnum相应的错误消息的指针
因为strerror函数返回的错误消息字符串所在的空间是静态分配的,所以当前的错误消息会被下一次strerror函数调用所覆盖。
如果传给它的参数errnum是非法的,那么它会返回“Unknown error nnn”,在某些实现上也可能返回NULL指针。
获取更多知识,请点击关注:
嵌入式Linux&ARM
CSDN博客
简书博客
知乎专栏