写给初学者的Linux errno 错误码机制
不同于Java的异常处理机制, 当你使用C更多的接触到是基于错误码的异常机制, 简单来说就是当调用的函数发生异常时, 程序不会跳转到一个统一处理异常的地方, 取而代之的是返回一个整型错误码。
可能会有小伙伴有疑问了, 以打开文件为例该函数定义如下所示
int open(const char *pathname, int flags);
如果打开文件成功, open
函数会返回一个文件描述符(该值大于0), 如果失败则返回-1
。对于开发者来说, 只知道文件打开失败了, 而却不知道具体原因, 实际上的原因可能是多种多样的, 如:
- 文件不存在
- 当前进程没有该文件的读写权限
那么该如何知道具体错误呢? 这就需要借助系统为我们提供的errno
机制了。
errno
errno是一个定义在errno.h
头文件的全局整型变量,表示当前发生的最后一个错误, 只需在代码中引用errno.h
这个头文件边可以获取到这个值。
如以下demo所示, 我们尝试打开一个不存在的文件
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
printf("open failed, errno: %d\n", errno);
}
return 0;
}
运行该程序, 输出如下所示:
open failed, errno: 2
可以看出,此时错误码为2
, 怎么知道这个错误码代表什么意思呢?
有以下方式
moreutils
- 安装moreutils
apt install moreutils
- 运行
errno 错误码
查看具体的错误信息
可以验证, 错误码2表示当前文件或目录不存在,与我们的预期一致
perror
使用定义在stdio.h
中的perror
函数可以直接在标准输出上打印错误信息
该函数定义如下所示, 我们可以在错误信息前附加自己定义的错误信息。
void perror(const char *s);
Demo:
int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
perror("open failed");
}
return 0;
}
输出:
strerr
如果我们只需要获取错误码对应的文本以记录日志, 可以使用strerr
函数, 该函数定义在string.h
中
Demo:
int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
char* err_msg = strerror(errno);
printf("%s\n", err_msg);
}
return 0;
}
输出
线程安全的吗?
相信对于并发问题比较敏感的同学已经意识到了一个问题:这errno
是一个整型的全局变量, 那如果多个线程同时执行系统调用, 并且都因为不同的原因失败了, 会不会导致其他线程的错误信息全部被最后一个产生错误的线程给覆盖掉了? 以及会不会有线程安全问题呢?
实际上errno
被定义为了线程局部变量, 概念同Java中的ThreadLocal
, 即每个线程都会有自己的errno变量, 不同线程之间不会互相影响。
写给初学者的Linux errno 错误码机制的更多相关文章
- linux的错误码error
在程序出错时,我们通过全局变量错误号errno和perror函数能够很快的定位到错误原因. Linux错误代码及其含义 C Name Value Description 含义Success 0 Suc ...
- errno 错误码
转自:http://baike.baidu.com/link?url=uX-q7K-TTL-5AFNT-hjhAP6fvgAwvsNkIMqJqJ3GEspYgtQXsovEEzpqmQ3ZmAgql ...
- Linux的错误码
在使用时需要包含头文件 #include <errno.h> merlin@tfAnalysis:~/projects/tfradius$ cat /usr/include/asm-gen ...
- errno错误码及含义(中文)
/usr/include/asm/errno.h #define EPERM 1 /* Operation not permitted */操作不允许 #define ENOENT 2 /* No s ...
- 写给初学者的话---linux使用说明
2018年noip上海赛区可以使用window操作系统的美梦终究还是破灭了!!!!上海大部分noip选手都陆陆续续开始改linux........好吧,那我们今天来看看linux操作系统中,noip选 ...
- Linux 内核错误码
#define EPERM 1 /* Operation not permitted */#define ENOENT 2 /* No such ...
- Linux环境下错误码及意义总结
Linux的错误码包含在/usr/include/asm-generic/errno-base.h和/usr/include/asm-generic/errno.h 这两个文件内: #ifndef _ ...
- .NET中异常与错误码优劣势对比
.NET之所以选择异常,而不是返回错误码来报告异常,是由于前者有以下几个优势: 1.异常与oop语言的结合性更好.oop语言经常需要对成员签名强加限制,比如c#中的构造函数.操作符重载和属性,开发者对 ...
- errno.h 错误码描述.
描述:一般说的Linux源码的目录,默认是基于 /usr/include/ 的. 使用 char *strerror(int errnum); 函数打印错误代码的描述.我简单对比了一下,发现描述大体一 ...
随机推荐
- linux环境下,使用Navicat连接mysql时,提示本地IP无法连接虚拟环境下的mysql解决方案
在Linux环境下,使用Navicat连接mysql时,提示本地IP无法连接虚拟环境下的mysql,提示如下: 而导致连接错误的原因是MYSQL没有开启远程登录权限. 解决方案: 在mysql命令中执 ...
- 三款超实用,好用的Python开发IDE推荐,看完总会有一款合适你的
@ 目录 前言 IDE介绍 Sublime Pycharm(推荐使用社区版免费版) visualstudio 倒底怎么选择 前言 一款好的代码编辑工具,让你学习事半功能,那今天就来看看我们学Pytho ...
- Phalcon多模块如何实现连接不同数据库 《Phalcon入坑指南系列 五》
本系列目录 一.Phalcon在Windows上安装 <Phalcon入坑指南系列 一> 二.Phalcon入坑必须知道的功能<Phalcon入坑指南系列 二> 三.Phalc ...
- [RabbitMQ]Java客户端:源码概览
本文简要介绍RabbitMQ提供的Java客户端中最基本的功能性接口/类及相关源码. Mavan依赖: <dependency> <groupId>com.rabbitmq&l ...
- windwos10安装mysql8.0.20详细图文教程
windwos10安装mysql8.0.20详细图文教程 1.浏览器搜索mysql下载安装 地址:https://dev.mysql.com/downloads/mysql/ 2.登录或者不登录下载 ...
- sqlite3 c++使用以及提高速率(一万条每秒左右)
参考来源: sqlite3的C语言使用(三):https://www.leavesongs.com/C/sqlite3_3.html sqlite插入和查询效率提高方法及测试结果: http://bl ...
- 题解 UVA1500 Alice and Bob
题目传送门 题目大意 给出 \(n\) 堆石子,每次可以做以下两种操作之一: 将某两堆石子进行合并 将某一堆石子抽走一个石子 问谁必胜. 思路 就nm很妙好么? 首先,我们需要考虑每堆石子大小都 \( ...
- 使用tinypng对需要上传Gitee图床的图片进行压缩
目录 背景 Tinypng简介 Tinypng使用 手动上传图片 使用API 调用API自动上传超过1MB图片 安装tinyfy 自动上传脚本 其他 背景 在使用Gitee作为图床时(使用Typora ...
- 在hive中使用COALESCE进行空值处理
COALESCE (expression_1, expression_2, ...,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值.如果所有的表达式都是空值,最终将返 ...
- 保护模式篇——PAE分页
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...