前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Linux系统调用API】七、errno()、strerror()、dup()、dup2()

【Linux系统调用API】七、errno()、strerror()、dup()、dup2()

作者头像
mindtechnist
发布2024-08-08 17:07:52
1470
发布2024-08-08 17:07:52
举报
文章被收录于专栏:机器和智能

1. 什么是errno

errno可以理解为一个全局变量,它存储了出错信息。在下面三个路径可以看到errno相关的内容

代码语言:javascript
复制
/usr/include/errno.h
/usr/include/asm-generic/errno-base.h
/usr/include/asm-generic/errno.h

我们可以在这些文件中自己定义一些errno,这样可以做到我们自己知道原始错误信息,而打印出来给用户看的是我们希望用户看到的对原始错误的解释。

2. strerror()函数

  • 包含头文件
代码语言:javascript
复制
#include <string.h>
  • 函数原型
代码语言:javascript
复制
char *strerror(int errnum);
  • 函数功能 可以打印errno对应的详细错误信息。The strerror() function returns a pointer to a string that describes the error code passed in the argument errnum, possibly using the LC_MESSAGES part of the current locale to select the appropriate language. This string must not be modified by the application, but may be modified by a subsequent call to perror(3) or strerror(). No library function will modify this string.
  • 函数参数
    • errnum:错误编号
  • 函数返回值 The strerror() functions return the appropriate error description string, or an "Unknown error nnn" message if the error number is unknown. 返回错误信息。

3. dup()和dup2()函数

  • 包含头文件
代码语言:javascript
复制
#include <unistd.h>
  • 函数原型
代码语言:javascript
复制
int dup(int oldfd);
int dup2(int oldfd, int newfd);

#define _GNU_SOURCE
#include <unistd.h>

int dup3(int oldfd, int newfd, int flags);
  • 函数功能 这两个函数主要用于重定向,它们两个的功能和区别就是:
  • dup(oldfd):复制文件描述符,返回一个当前空闲的最小文件描述符,并且让这个文件描述符指向oldfd所指向的文件;dup() uses the lowest-numbered unused descriptor for the new descriptor.
  • dup2(oldfd, newfd):重定向,关闭newfd对应的文件使文件描述符newfd空闲,然后让newfd指向oldfd所指向的文件;dup2() makes newfd be the copy of oldfd, closing newfd first if necessary, but note the following: If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed. If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.
  • 函数参数
    • oldfd:旧的文件描述符
    • newfd:新的文件描述符
  • 函数返回值
    • On success, these system calls return the new descriptor.
    • On error, -1 is returned, and errno is set appropriately.

示例:一句话打印两次,先打入文件,后打至屏幕

代码语言:javascript
复制
/************************************************************
  >File Name  : dup_test.c
  >Author     : QQ
  >Company    : QQ
  >Create Time: 2022年05月17日 星期二 16时09分41秒
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        printf("not found string\n");
        return -1;
    }   
    /*每开启一个进程,默认打开 0 1 2 三个文件描述符*/
    /*首先备份标准输出*/
    int stdoutfd = dup(STDOUT_FILENO);
    /*打开一个文件*/
    int fd = open("hello.txt", O_WRONLY | O_CREAT, 0644);
    /*重定向标准输出1至文件*/
    dup2(fd, STDOUT_FILENO);    
    printf("first: %s\n", argv[1]);
    
    /*  ===========================
    printf会进行系统调用,需要刷新buffer
        ===========================
    
    fflush(stdout);
    */
    
    /*恢复标准输出*/
    dup2(stdoutfd, STDOUT_FILENO);
    printf("second: %s\n", argv[1]);
    close(fd);
    return 0;
}

我们编译运行一下,你会发现两次都打印在了屏幕上,其实这就是我们在《系统API与C库函数的调用关系》中讲的系统调用问题,C库函数printf()会调用系统API函数write(),这是会用到一个文件指针,这里面有一个缓冲区buffer,要打印的内容会先放入到buffer中,如果我们在第一次调用printf()函数后不刷新这个buffer缓冲区的话,在第二次打印的时候,buffer就会保留有上次调用时放入缓冲区的内容,所以打印到标准输出时,打印了两句话。

注意:这里的 "hello\ linux" 中,"\ " 使通过转义符把空格的特殊含义去掉,如果不加转义符,shell会把空格分开的内容当作两个字符串,通过转义符就可以实现在字符串中写入空格,这是shell的知识。

解决方法就是在第二次打印前刷新一下缓冲区,将上面代码中的fflush()函数放出即可

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器和智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是errno
  • 2. strerror()函数
  • 3. dup()和dup2()函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档