linux系统编程之错误处理机制

在讲解liunx错误处理机制之前我们先来看一段代码:

 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<fcntl.h>
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6
 7 int main(void)
 8 {
 9     int fd;
10     fd=open("abc",O_WRONLY);
11     if(fd<0){
12         printf("Error:fd=%d\n",fd);
13         14     }
15
16     return 0;
17 }

这一段代码是用函数open打开一个名为abc的文件,open函数的帮助文档如下:

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

翻译过来就是open()函数返回一个新的文件描述符,如果出现错误,则返回-1(在出现错误的情况下,errno要被做相应的设置)

我们上面的代码只是判断了open是否发生了错误,至于是什么错误无法判断。因为可以引起上述代码中open函数错误的原因比较多,例如文件abc不存在,或者文件abc存在,但是没有写的权限。这都会出现错误。那么要怎么样准确的判定是什么引起的open函数处错误的呢?

从上面的帮助文档我们知道,当open函数出错时,不仅仅会返回一个-1,函数设置errno的值。那么errno是什么类型的呢?我们看一下errno的声明或者定义

在文件/usr/include/errno.h里面有下面的代码

#ifndef errno

 extern int errno;
 
#endif

从这里我们可以看到errno是一个整型,并且是一个全局的整型变量。

其实 errno是一个错误编号,当错误发生时,每一个不同的错误都有一个编号,这个编号的值就会被存储在errno中,根据这个编号系统就可以判断是什么错误发生了,既然系统可以判断是什么错误发生,那么就可以把错误的信息打印出来。打印错误信息的函数是perror(),当然还有一些别的打印错误的函数,我们这里就不举例了,如果想查看,可以通过man 2 perror来查看帮助文档。下面我们列举一些错误的定义,错误编号的定义放在/usr/include/asm-generic/目录的errno-base.h 以及errno.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 */
                                                                                                        1,1          顶端

这时我们就可以改写测试程序了

 1 #include<sys/types.h>
 2 #include<sys/stat.h>
 3 #include<fcntl.h>
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6
 7 int main(void)
 8 {
 9     int fd;
10     fd=open("abc",O_WRONLY);
11     if(fd<0){
12         printf("Error:fd=%d\n",fd);
13         perror("open file abc");//这一行就是根据系统的编号打印出错误的信息
14     }
15
16     return 0;
17 }
18 ~       
时间: 2024-08-26 06:02:18

linux系统编程之错误处理机制的相关文章

linux系统编程之错误处理

在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 1 #ifndef _ERRNO_H 2 3 /* The includer defined __need_Emath if he wants only the definitions 4 of EDOM and ERANGE, and not everything else. */ 5 #ifndef __need_Emath 6 #

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt

嵌入式 Linux系统编程(三)——标准IO库

嵌入式 Linux系统编程(三)--标准IO库 与文件IO函数相类似,标准IO库中提供的是fopen.fclose.fread.fwrite等面向流对象的IO函数,这些函数在实现时本身就要调用linux的文件IO这些系统调用. 一.标准IO库函数的缓冲机制 由于IO设备的访问速度与CPU的速度相差好几个数量级,为了协调IO设备与CPU的速度的不匹配,对于块设备,内核使用了页高速缓存,即数据会先被拷贝到操作系统内核的页缓存区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间. 当应用程序尝

Linux系统编程【转】

转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准C库.系统调用封装.线程库.基本应用工具 gcc: 1.2 模块接口 API:应用程序编程接口,源代码级别,能通过编译,由标准C语言定义,libc来实现 ABI:应用程序二进制接口,二进制级别,能正常运行,关注调用约定.字节序.寄存器使用.系统调用.链接.二进制格式等,很难实现 1.3 错误处理 <

Linux系统编程-setitimer函数

功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); 参数含义: 1.which参数用来设置定时器类型,可选的值为 (1)ITIMER_REAL : 设置定时器以系统真实所花费的时间来计时,运行指定时间后发送SIGALRM信号. (

linux系统编程之管道(一):匿名管道(pipe)

原文地址:http://www.cnblogs.com/mickole/p/3192210.html 一,什么是管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 数据的读

Linux系统编程札记:进程通信(一) &nbsp; &nbsp;

进程简单来讲就是一个程序的一次执行,这里说的进程一般都指的是运行在用户态的进程,而处于用户态的不同进程之间是彼此相互隔离的,它们必须通过某种方式来进行通信,具体理由如下: (1)数据传输:有时候一个进程需要将它的数据发送给另一个进程. (2)资源共享:有时候多个进程之间需要共享同样的资源. (3)通知事件:有时候一个进程需要向另一个或一组进程发送消息,通知它们发生了某个事件. (4)进程控制:有些进程希望能够完全控制另一个进程的执行,此时控制进程希望能够拦截另一进程的所有操作,并能够及时知道它的

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

嵌入式 Linux系统编程(四)——文件属性

嵌入式 Linux系统编程(四)--文件属性 一.文件属性概述 Linux 文件的属性主要包括:文件的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.文件属性示例如下: 多个文件属性查看: ls -lih 1341714 -rw-r--r-- 1 root root 2.5K May 28 10:24 bit_marco.c 1341718 -rw-r--r-- 1 root root 2.1K May 28 09:08 bit_marco.c~ 1341706