zoukankan      html  css  js  c++  java
  • 系统编程-文件IO-dup和dup2系统调用

    在linux下,一切皆文件。

    文件描述符用于操作文件。

    从shell中运行一个进程,默认会有3个文件描述符存在(0、1、2);)0表示标准输入,1表示标准输出,2表示标准错误。

    一个进程当前有哪些打开的文件描述符可以通过/proc/进程ID/fd目录查看。

     

    1、 dup函数

    #include <unistd.h>
    int dup(int oldfd);

    功能:复制一个文件描述符

    返回值:成功则返回一个新的文件描述符,失败则返回-1。

    当复制成功时,返回值是当前进程可用的最小的文件描述符,返回的新文件描述符和参数oldfd指向同一个文件,

    若有错误则返回-1,错误代码存于errno中。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd = open("a.txt", O_RDWR | O_CREAT);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
    printf(
    "file open fd = %d ", fd); // 找到进程文件描述表中第一个可用的文件描述符A // 将参数指定的文件描述符B复制给A,并返回A int fd2 = dup(fd); if(fd2 == -1) { perror("dup"); exit(1); } printf("dup fd = %d ", fd2); char* buf = "hello"; char* buf1 = " world "; write(fd, buf, strlen(buf)); write(fd2, buf1, strlen(buf1)); close(fd); return 0; }
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# ./ab
    file open fd = 3
    dup fd = 4
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# cat a.txt 
    hello world
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# 

    2. dup2函数

    #include <unistd.h>
    int dup2(int oldfd, int newfd);

    功能:复制一个文件描述符,且指定文件描述符newfd为oldfd的复制版本。

    返回值:成功返回newfd,失败返回-1。

    dup2函数成功返回时,目标描述符(函数第二个参数,newfd)将变成源描述符(函数第一个参数,oldfd)的复制品,

    即,两个文件描述符现在都指向同一个文件,并且是源描述符指向的文件。

    若有错误则返回-1,错误代码存于errno中。 

    dup2详解:

    ①、如果newfd已经打开,则先将其关闭,再指定文件描述符newfd为oldfd的复制版本。
    ②、如果newfd等于oldfd,则dup2直接返回newfd, 而不关闭它。

    //测试dup2函数
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd = open("b.txt", O_RDWR | O_CREAT);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
    
        int fd1 = open("a.txt", O_RDWR);
        if(fd1 == -1)
        {
            perror("open");
            exit(1);
        }
    
        printf("fd = %d
    ", fd);
        printf("fd1 = %d
    ", fd1);
    
        int curfd = dup2(fd, fd1);  //让fd1和fd同时指向b.txt
        if(curfd == -1)
        {
            perror("dup2");
            exit(1);
        }
        printf("current fd = %d
    ", curfd);
        char* buf = "hello
    ";
        char* buf1 = "world!
    ";
        write(fd, buf, strlen(buf));
        write(fd1, buf1 , strlen(buf1));
    
        close(fd);
        close(fd1);
    return 0;
    }

     编译运行:

    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# gcc dup2.c -o ab
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# ./ab
    fd = 3
    fd1 = 4
    current fd = 4
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# cat b.txt 
    hello
    world!
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# cat a.txt 
    hello world  
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# 

    实验前后,a.txt的内容未发生改变,同时根据实验后b.txt的内容,证实了dup2函数功能的有效性。

     

    注意:
    通过dup和dup2创建的文件描述符,不继承原文件描述符的close-on-exec和non-blocking属性。

     

    细节补充:

    int dup(int oldfd);

    dup函数:函数执行成功时,新得到的文件描述符和oldfd,共享文件偏移量和文件状态。

    共享偏移量测试代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    // off_t lseek(int fd, off_t offset, int whence);第二个参数是偏移量,第三个参数是起始地址,要注意区分
    int main(int argc, char const *argv[])
    {
        int fd = open("b.txt", O_RDONLY);
    
      //1. 先复制fd,得到copyfd    
        int copyFd = dup(fd);
    
      //2. 然后对fd、copyfd中的一个文件描述符进行操作,观察另一个文件描述符的变化
        //置fd对应的当前文件数据索引偏移量到文件尾
        unsigned long offset = lseek(fd, 0, SEEK_END);
    
        // 打印偏移量
        printf("fd = %d , 距离文件头的偏移量:%ld
    ", fd, offset); 
        
        //打印copyFd的文件数据索引偏移量
        printf("copyFd = %d , 距离文件头的偏移量:%ld
    ", copyFd, lseek(copyFd, 0, SEEK_CUR)); 
    
        return 0;
    }

    编译运行:

    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# gcc dup_2.c -o ab
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# ./ab
    fd = 3 , 距离文件头的偏移量:14
    copyFd = 4 , 距离文件头的偏移量:14
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# 
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# 

    现象和结论:使用了dup,操纵fd的文件数据索引偏移,导致copyfd的偏移量也跟着移动到了文件末尾。

    int dup2(int oldfd, int newfd);

    dup2函数:函数执行成功时,新得到的文件描述符newfd和oldfd,共享文件偏移量和文件状态。

    共享偏移量测试代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main(int argc, char const *argv[])
    {
        int fd = open("b.txt", O_RDONLY);
        int newfd;
    
      //1. 获取有效的newfd
        newfd = dup2(fd, 14);
    
      //2. 然后对fd、newfd中的一个文件描述符进行操作,观察另一个文件描述符的变化
        //置fd对应的文件数据索引偏移到文件尾
        unsigned long offset = lseek(fd, 0, SEEK_END);
    
        // 打印偏移量
        printf("fd = %d , 距离文件头的偏移量:%ld
    ", fd, offset); 
        
        //打印newfd的文件数据索引偏移
        printf("newfd = %d , 距离文件头的偏移量:%ld
    ", newfd, lseek(newfd, 0, SEEK_CUR)); 
    
        return 0;
    }

    编译运行:

    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# gcc dup_2.c -o ab
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# ./ab
    fd = 3 , 距离文件头的偏移量:14
    newfd = 14 , 距离文件头的偏移量:14
    root@lmw-virtual-machine:/home/lmw/桌面/linux_system_program/dup2_dup# 

    现象和结论:使用了dup2,操纵fd的文件数据索引偏移,导致newfd的偏移量也跟着移动到了文件末尾。

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    leetcode 18 4Sum
    leetcode 71 Simplify Path
    leetcode 10 Regular Expression Matching
    leetcode 30 Substring with Concatenation of All Words
    leetcode 355 Design Twitte
    leetcode LRU Cache
    leetcode 3Sum
    leetcode Letter Combinations of a Phone Number
    leetcode Remove Nth Node From End of List
    leetcode Valid Parentheses
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/13771788.html
Copyright © 2011-2022 走看看