Linux perror函数详解——错误信息输出利器 (linux perror())
Linux系统作为一款高性能、高稳定性的操作系统,其应用广泛,特别是在服务器领域。在使用Linux时,经常会出现各种错误,如网络连接错误、文件读写错误等。为了诊断并解决这些错误,Linux提供了众多的工具和函数,其中perror函数就是其中一个错误信息输出利器。
一、perror函数概述
perror函数是一个错误信息输出函数,其主要作用是将errno对应的错误信息输出到标准错误输出中(stderr)。该函数的原型如下:
“`C
#include
void perror(const char *s);
“`
perror函数只需要一个参数s,表示输出错误信息时的前缀字符,通常为程序名或相关信息。
二、perror函数使用示例
以下是一个使用perror函数的示例代码:
“`C
#include
#include
int mn()
{
FILE *fp;
char *filename = “not_exist.txt”;
fp = fopen(filename, “r”);
if (fp == NULL)
{
perror(“fopen error”);
printf(“errno=%d\n”, errno);
return 1;
}
fclose(fp);
return 0;
}
“`
上述代码中,我们尝试以只读方式打开一个不存在的文件,这会导致fopen函数返回一个空指针。在判断文件打开是否成功之后,我们调用了perror函数输出了错误信息。由于文件不存在,因此errno的值被设置为ENOENT,perror函数会将对应的错误信息输出到stderr中。执行该代码,输出结果如下:
“`
fopen error: No such file or directory
errno=2
“`
可以看到,perror函数输出了对应的错误信息“No such file or directory”,并且打印了errno的值为2,这正是ENOENT的值。
三、perror函数与errno变量
perror函数和errno变量是紧密相关的,errno变量定义在errno.h头文件中,其主要作用是存储最近一次系统调用发生错误时的错误码。每个错误码对应一个宏定义,例如ENOENT表示文件不存在,EACCES表示权限不足等。
通过perror函数,我们可以根据errno的值输出对应的错误信息,方便定位并解决错误。在使用perror函数时,需要先include errno.h头文件,以便正确使用errno变量。
四、perror函数源代码分析
perror函数的源代码实现如下:
“`C
#include “stdio_impl.h”
void perror(const char *msg)
{
int e = errno, oldtype;
__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype);
__stdio_flockfile(stderr);
if (msg && *msg)
__stdio_fputs(msg, stderr);
__stdio_fputs(“: “, stderr);
__stdio_fputs(strerror(e), stderr);
__stdio_putc(‘\n’, stderr);
__stdio_funlockfile(stderr);
__pthread_setcancelstate(oldtype, 0);
}
“`
可以看到,perror函数主要分为以下几个步骤:
1. 获取当前errno的值;
2. 禁用线程取消;
3. 对标准错误流(stderr)加锁,以避免多线程中的输出混乱;
4. 如果msg不为空,则将其作为前缀输出到stderr中;
5. 输出errno对应的错误信息;
6. 输出换行符;
7. 解锁标准错误流;
8. 恢复线程取消状态。
通过分析源代码,我们可以了解到perror函数的实现原理,并且可以更好地理解其使用方法。
五、
相关问题拓展阅读:
- linux关于管道说法错误的是什么
linux关于管道说法错误的是什么
Linux关于管道 原创
:22:41
Gaodes
码龄5年
关注
管道的概念
管道是Unix中枣镇蔽最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道” 我们通常把是把一个进程的输出连接或“管接”(经过管道来连接)到另一个进程的输入。
管道特点
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道 只能用于父子进程或者兄弟进程之间(具有亲凳州缘关系的进程)进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
pipe函数
包含头文件 功能:创建一无名管道 原型
int pipe(int file_descriptor);
参数 file_descriptor:文件描述符数组,其中file_descriptor表示读端,file_descriptor表示写端 返回值:成功返回0,失败返回错误代码
示例代码:
#include
#include
#include
#include
#include
int main(int argc,char *argv)
{
int fd;
printf(“f=%d,f=%d\n”,fd,fd);
pipe(fd);
printf(“f=%d,f=%d\n”,fd,fd);
char buf={0};
int fid = fork();
if(fid > 0)
{
read(fd,buf,1024);
printf(“read data %s\n”,buf);
}
else if(fid == 0)
{
write(fd,”helloworld”,strlen(“helloworld”));
}
else
{
perror(“fork error”);
}
return 0;
}
打印结果
管道读写规则:如果试图从管道写端旅塌读取数据,或者向管道读端写入数据都将导致错误发生 当没有数据可读时,read调用就会阻塞,即进程暂停执行,一直等到有数据来到为止。 如果管道的另一端已经被关闭,也就是没有进程打开这个管道并向它写数据时,read调用就会阻塞
复制文件描述符dup
#include
#include
#include
#include
int main()
{
int fd = dup(1);
printf(“file fd= %d\n”,fd);
write(fd,”helloworld”,strlen(“helloworld”));
return 0;
}
打印结果:
1为输入到终端
shell管道的实现
原理通过把发的fd写复制到shell的1(标准输入),fd复制到shell的2(标准输出)
以下是代码:
#include
#include
#include
#include
#include
#include
int main()
{
int fd;
char buf ={0};
pipe(fd);
int pid = fork();
if(pid > 0)
{
read(fd,buf,1024);
printf(buf);
}
else if(pid == 0)
{
dup2(fd,1);
close(fd);
close(fd);
execlp(“ls”,”ls”,”-al”,NULL);
}
else
{
}
return 0;
}
实现结果:
popen函数
作用:允许一个程序把另外一个程序当作一个新的进程来启动,并能对它发送数据或接收数据
FILE* popen(const char *command, const char *open_mode);
command:待运行程序的名字和相应的参数 open_mode:必须是“r”或“w” 如果操作失败,popen会返回一个空指针
以下代码:
#include
#include
#include
#include
#include
#include
int main()
{
FILE *file = popen(“ls -al”,”r”);
char buf = {0};
fread(buf,1,1024,file);
fclose(file);
FILE *wcfile = popen(“wc”,”w”);
fwrite(buf,1,strlen(buf),wcfile);
fclose(wcfile);
return 0;
}
代码结果:
命名管道破裂测试
我们首先要知道命名管道,要读段和写段同时开启,才能向文件读写数据。
贴上代码来理解命名管道的规则
首先是读端:
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv)
{
printf(“open before\n”);
int fd = open(“/home/gao/tmp/fifo”,O_RDON);
printf(“open after\n”);
//休眠5秒,读端退出
sleep(5);
return 0;
}
接下来是写端:
#include
#include
#include
#include
#include
#include
void handle(int signo)
{
printf(“cat signale = %d\n”,signo);
}
int main(int argc,char *argv)
{
signal(SIGPIPE,handle);
printf(“open before\n”);
int fd = open(“/home/gao/tmp/fifo”,O_WRON);
printf(“open after\n”);
//命名管道规则,如果写入读断被中断,写入会返回-1,并且管道会破裂,产生信号(SIGPIPE)
while(1)
{
int wrsize = write(fd,”helloworld”,strlen(“helloworld”));
printf(“size data:%d\n”,wrsize);
sleep(1);
}
}
执行写端:
它在等待另一端的开启,才能向里面写入数据
此时我们开启读端:
马上可以看到写段可以写数据
而执行5秒后,我们可以看到写的时候返回-1,并且获取到管道破裂的信息(SIGPIPE)
linux perror()的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux perror(),Linux perror函数详解——错误信息输出利器,linux关于管道说法错误的是什么的信息别忘了在本站进行查找喔。
编辑:一起学习网
标签:管道,函数,进程,错误信息,错误