• 五、文件IO——dup 函数


    5.1 dup 函数---复制文件描述符

    5.1.1 简单cat实现及输入输出重定向

      io.c

     1 #include <sys/types.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <unistd.h>
     5 #include "io.h"
     6 #include <string.h>
     7 #include <errno.h>
     8 #include <stdlib.h>
     9 #include <stdio.h>
    10 #include <fcntl.h>
    11 
    12 
    13 #define BUFFER_LEN 1024
    14 
    15 /* 文件的读写拷贝 */
    16 void copy(int fdin, int fdout)
    17 {
    18     char buff[BUFFER_LEN];
    19     ssize_t size;
    20 
    21 //    printf("file length: %ld
    ", lseek(fdin, 0L, SEEK_END));//将文件定位到文件尾部,偏移量为0L
    22 //    lseek(fdin, 0L, SEEK_SET);// 定位到文件开头
    23 
    24     while((size = read(fdin, buff, BUFFER_LEN)) > 0) { //从 fdin 中读取 BUFFER_LEN 个字节存放入  buff 中
    25 //        printf("current: %ld
    ", lseek(fdin, 0L, SEEK_CUR));
    26 
    27         if(write(fdout, buff, size) != size) {
    28             fprintf(stderr, "write error: %s
    ", strerror(errno));
    29             exit(1);
    30         }
    31     }
    32     if(size < 0) {
    33         fprintf(stderr, "read error:%s
    ", strerror(errno));
    34         exit(1); // 相当于 return 1;
    35     }
    36 }

      cat.c

     1 #include <sys/types.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <unistd.h>
     5 #include "io.h"
     6 #include <string.h>
     7 #include <errno.h>
     8 #include <stdlib.h>
     9 #include <stdio.h>
    10 #include <fcntl.h>
    11 
    12 int main(int argc, const char *argv[])
    13 {
    14     int fd_in = STDIN_FILENO;
    15     int fd_out = STDOUT_FILENO;
    16     int i;
    17 
    18     for(i = 1; i < argc; i++) {
    19         fd_in = open(argv[i], O_RDONLY);
    20         if(fd_in < 0) {
    21             perror("open error");
    22             continue;
    23         }
    24 
    25         copy(fd_in, fd_out);
    26         close(fd_in);
    27     }
    28 
    29     if(argc == 1)
    30         copy(fd_in, fd_out);
    31 
    32     return 0;
    33 }

      编译:gcc -o bin/cat -Iinclude src/io.c src/cat.c

      调试:

      

      

      

      cat 的作用就输入和输出的重定向功能,而 dup 和 dup2 就是用来完成此功能的。

    5.1.2 dup 和 dup2 函数说明

    1 #include<unistd.h>
    2 int dup (int oldfd);
    3 int dup2(int odlfd,int newfd);
    • 函数说明:
      • dup() 用来复制参数 oldfd 所指的文件描述符,并将它返回。此新的文件描述符和参数oldfd指的是同一个文件,共享所有的锁定、读写位置和各项权限或旗标。例如,当利用 lseek() 对某个文件描述符作用时,另一个文件描述词的读写位置也会随着改变。不过,文件描述符之间并不共享 close-on-exec 旗标。  
      • dup2() 用来复制参数 oldfd 所指的文件描述符,并将它拷贝至参数 newfd 后一块返回。若参数 newfd 为一已打开的文件描述词,则 newfd 所指的文件会先被关闭。如若 oldfd 等于 newfd,则dup2 返回 newfd,而不关闭它。dup2() 所复制的文件描述符,与原来的文件描述符共享各种文件状态,详情可参考 dup() 。
    • 参数:
      • oldfd:原先的文件描述符
      • newfd:新的文件描述符  
    • 返回值:当复制成功时,则返回最小及尚未使用的文件描述符。若有错误则返回-1,errno会存放错误代码。
    • 附加说明:
      • dup2() 相当于调用 fcntl(oldfd,F_DUPFD,newfd);请参考 fcntl()  
      • 在进程间通信时可用来改变进程的标准输入和标准输出。

      文件描述符的赋值是文件描述符表结构体成员中指针的复制。

      

      dup2(fd_in, STDIN_FILENO),相当于就是将 fd_in 文件描述符中的指向文件表项的指针赋值给 STDIN_FILENO 中的指向标准输入的指针,此时,STDIN_FILENO 中的指针指向了fd_in 中的指针指向的文件表项(地址一样了),最终指向了读取的文件。

      则此时 dup1 中 STDIN_FILENO 不再是从标准输入读取,而是从 fd_in 中去读取。这种就是重定向

     5.1.3 实例

      将+ 和 - 改为输入输出重定向

       mcat.c

     1 #include <sys/types.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <unistd.h>
     5 #include "io.h"
     6 #include <string.h>
     7 #include <errno.h>
     8 #include <stdlib.h>
     9 #include <stdio.h>
    10 #include <fcntl.h>
    11 
    12 /*
    13  * bin/mcat + append.txt(+ 为输入重定向)
    14  * bin/mcat - append.txt(- 为输出重定向)
    15  */
    16 int main(int argc, const char *argv[])
    17 {
    18     int fd_in;
    19     int fd_out;
    20     int i;
    21     int flag = 0;
    22 
    23     for(i = 1; i < argc; i++) {
    24         if(!strcmp("+", argv[i])) {
    25             fd_in = open(argv[++i], O_RDONLY);
    26             if(fd_in < 0) {
    27                 perror("open error");
    28                 exit(1);
    29             }
    30 
    31             //将标准输入重定向到文件
    32             if(dup2(fd_in, STDIN_FILENO) != STDIN_FILENO) {
    33                 perror("dup2 error");
    34                 exit(1);
    35             }
    36 
    37             close(fd_in);
    38         } else if(!strcmp("-", argv[i])) {
    39             fd_out = open(argv[++i], O_WRONLY | O_CREAT | O_TRUNC, 0777);
    40             if(fd_out < 0) {
    41                 perror("open error");
    42                 exit(1);
    43             }
    44             
    45             //将标准输出重定向到文件
    46             if(dup2(fd_out, STDOUT_FILENO) != STDOUT_FILENO) {
    47                 perror("dup2 error");
    48                 exit(1);
    49             }
    50 
    51             close(fd_out);
    52 
    53         } else {
    54             flag = 1;
    55             fd_in = open(argv[i], O_RDONLY);
    56             if(fd_in < 0) {
    57                 perror("open error");
    58                 exit(1);
    59             }
    60 
    61             if(dup2(fd_in, STDIN_FILENO) != STDIN_FILENO) {
    62                 perror("dup2 error");
    63                 exit(1);
    64             }
    65 
    66             copy(STDIN_FILENO, STDOUT_FILENO);
    67             close(fd_in);
    68         }
    69     }
    70 
    71     if(!flag) {
    72         copy(STDIN_FILENO, STDOUT_FILENO);
    73     }
    74 
    75     return 0;
    76 }

      编译调试如下:

      

  • 相关阅读:
    在Mybatis中使用连表查询的一次实际应用
    Mybatis使用generatedKey在插入数据时返回自增id始终为1,自增id实际返回到原对象当中的问题排查
    一次org.springframework.jdbc.BadSqlGrammarException ### Error querying database Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException问题排查过程
    商品的spu、sku及其之间的关系
    Java transient关键字的理解
    关于Serializable的一个形象的例子
    一个很大的文件,存放了10G个整数的乱序数列,如何用程序找出中位数。
    Logger.error方法之打印错误异常的详细堆栈信息
    什么是Http无状态?Session、Cookie、Token三者之间的区别
    接口API中的敏感数据基于AES进行安全加密后返回
  • 原文地址:https://www.cnblogs.com/kele-dad/p/9033347.html
Copyright © 2020-2023  润新知