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的偏移量也跟着移动到了文件末尾。

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    响应式设计的5个CSS实用技巧
    jquery获取浏览器高度、宽度和滚动条高度
    jquery和其他库发生冲突的解决办法
    雅虎的14条性能优化原则
    手机网站前端开发布局技巧
    手机网站前端开发经验总结
    -webkit-scrollbar
    as3中TextFormat类的使用
    flash全屏后的UI控制
    字符串类的算法题
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/13771788.html
Copyright © 2011-2022 走看看