写给初学者的Linux|写给初学者的Linux errno 错误码机制
不同于Java的异常处理机制, 当你使用C更多的接触到是基于错误码的异常机制, 简单来说就是当调用的函数发生异常时, 程序不会跳转到一个统一处理异常的地方, 取而代之的是返回一个整型错误码。
可能会有小伙伴有疑问了, 以打开文件为例该函数定义如下所示
int open(const char *pathname, int flags);
如果打开文件成功,
open
函数会返回一个文件描述符(该值大于0), 如果失败则返回-1
。对于开发者来说, 只知道文件打开失败了, 而却不知道具体原因, 实际上的原因可能是多种多样的, 如:- 文件不存在
- 当前进程没有该文件的读写权限
errno
机制了。errno errno是一个定义在
errno.h
头文件的全局整型变量,表示当前发生的最后一个错误, 只需在代码中引用errno.h
这个头文件边可以获取到这个值。如以下demo所示, 我们尝试打开一个不存在的文件
#include
#include
#include
#include 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 错误码
查看具体的错误信息
文章图片
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变量, 不同线程之间不会互相影响。推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量