我是靠谱客的博主 单薄麦片,最近开发中收集的这篇文章主要介绍Linux系统调用API容错机制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

以open函数为例,该系统API原型为:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

在c语言中,是不可能存在相同函数名的两个函数的,那么可以知道open函数是一个可变参函数,即

open(const char *pathname, int flags, ...)

当flags取值含O_CREAT(文件不存在则创建)值时,可变参用来指定新建的该文件的属性。
根据man手册介绍,open的返回值及容错机制都有说到

open() and creat() return the new file descriptor, or -1 if an error occurred (in which case, errno is set appropriately).

即open()和create()函数如果执行成功就返回该文件的文件描述符,失败则返回-1,失败的原因会被记录在errno中。再往手册下看,可以看到errno的取值,有EACCES,EEXIST,EFAULT,EFBIG等等。可以推测,这些取值是一些宏定义。该API都退出了,还可以打印errno的值来得到错误标识码,所以这些量肯定是全局变量。既然如此,那么这个errno肯定是不可重入的,也就是说它记录的是最近一次API调用的错误码。
这些宏的定义在/usr/include/asm-generic/errno-bash.h中:

#define EPERM
1
/* Operation not permitted */
#define ENOENT
2
/* No such file or directory */
#define ESRCH
3
/* No such process */
#define EINTR
4
/* Interrupted system call */
#define EIO
5
/* I/O error */
#define ENXIO
6
/* No such device or address */
#define E2BIG
7
/* Argument list too long */
#define ENOEXEC
8
/* Exec format error */
#define EBADF
9
/* Bad file number */
#define ECHILD
10
/* No child processes */
#define EAGAIN
11
/* Try again */
#define ENOMEM
12
/* Out of memory */
#define EACCES
13
/* Permission denied */
#define EFAULT
14
/* Bad address */
#define ENOTBLK
15
/* Block device required */
#define EBUSY
16
/* Device or resource busy */
#define EEXIST
17
/* File exists */
#define EXDEV
18
/* Cross-device link */
#define ENODEV
19
/* No such device */
#define ENOTDIR
20
/* Not a directory */
#define EISDIR
21
/* Is a directory */
#define EINVAL
22
/* Invalid argument */
#define ENFILE
23
/* File table overflow */
#define EMFILE
24
/* Too many open files */
#define ENOTTY
25
/* Not a typewriter */
#define ETXTBSY
26
/* Text file busy */
#define EFBIG
27
/* File too large */
#define ENOSPC
28
/* No space left on device */
#define ESPIPE
29
/* Illegal seek */
#define EROFS
30
/* Read-only file system */
#define EMLINK
31
/* Too many links */
#define EPIPE
32
/* Broken pipe */
#define EDOM
33
/* Math argument out of domain of func */
#define ERANGE
34
/* Math result not representable */

测试代码: 可读可写打开当前目录的errno_test文件,但是当前目录并不存在该文件或者目录

int main(void)
{
int fd;
fd = open("./errno_test", O_RDWR);
if (fd < 0)
{
printf("errno: %dn", errno);
}
close(fd);
return 0;
}

运行结果:
这里写图片描述
错误码2对应到宏是ENOENT,上面注释也已说明: “No such file or directory”。
对于API使用者来说,一个错误标识码表达错误信息显然还不够对明朗,每次拿到标注码后还要去对照宏定义(的注释内容)显然十分不方便。既然这些标识码有与之对应的错误信息,何不将他们封装成一个指针数组,指针指向错误信息字符串?这样每次拿到错误标注码后就可以作为下标索引得到数组中的错误信息了。
当然,这么简单是事情,标准c库的perror函数已经为我们实现了:

int main(void)
{
int fd;
fd = open("./errno_test", O_RDWR);
if (fd < 0)
{
//printf("errno: %dn", errno);
perror("open");
}
close(fd);
return 0;
}

运行结果:
这里写图片描述
perror的用法,也十分巧妙。
Linux API的这种设计方法,值得我们在项目开发中借鉴。

最后

以上就是单薄麦片为你收集整理的Linux系统调用API容错机制的全部内容,希望文章能够帮你解决Linux系统调用API容错机制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(76)

评论列表共有 0 条评论

立即
投稿
返回
顶部