• Linux系统编程笔记--系统(文件)I/O操作


    目录

    1--文件描述符

    2--系统I/O常用函数

    3--标准I/O和系统I/O的区别

    4--原子操作

    5--dup()和dup2()

    6--fcntl()和ioctl()


    1--文件描述符

            文件描述符的实质:一个整型数,一个数组下标(数组的元素指向文件结构体);

            文件描述符优先使用可用范围内最小的;

            标准输入(stdin)的文件描述符为 0;标准输出(stdout)的文件描述符为 1;标准错误(stderr)的文件描述符为 2;因此其余文件描述符肯定 >= 3;

    2--系统I/O常用函数

    以下常用函数可通过 man 手册查看其用法;

            open():

            close():

            read();

            write();

    1. int open(const char *pathname, int flags);
    2. int close(int fd);
    3. ssize_t read(int fd, void *buf, size_t count);
    4. ssize_t write(int fd, const void *buf, size_t count);
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #define BUF_SIZE 1024
    7. int main(int argc, char* argv[]){
    8. int sfd, dfd;
    9. char* buf[BUF_SIZE];
    10. int len, ret, pos;
    11. if(argc < 3){
    12. fprintf(stderr, "Usage...\n");
    13. exit(1);
    14. }
    15. sfd = open(argv[1], O_RDONLY);
    16. if(sfd < 0){
    17. perror("open()");
    18. exit(1);
    19. }
    20. dfd = open(argv[2], O_WRONLY|O_CREAT, O_TRUNC, 0600);
    21. if(dfd < 0){
    22. close(sfd);
    23. perror("open()");
    24. exit(1);
    25. }
    26. printf("%d %d\n", sfd, dfd); // 3 4
    27. while(1){
    28. len = read(sfd, buf, BUF_SIZE);
    29. if(len < 0 ){
    30. perror("read()");
    31. break;
    32. }
    33. if(len == 0) break;
    34. pos = 0;
    35. while(len > 0){
    36. ret = write(dfd, buf+pos, len);
    37. if(ret < 0){
    38. perror("write()");
    39. exit(1);
    40. }
    41. pos += ret;
    42. len -= ret;
    43. }
    44. }
    45. close(dfd);
    46. close(sfd);
    47. exit(0);
    48. }

    3--标准I/O和系统I/O的区别

            标准I/O的吞吐量大(会先把数据放到缓冲区,刷新缓冲区之后才会完成数据的存取),系统I/O的响应速度快(不会把数据放到缓冲区,一次调用就完成一次操作);

            标准I/O和系统I/O最好不要混用;

            标准I/O和系统I/O的转换函数:fileno() fdopen()

    1. int mian(){
    2. putchar('a');
    3. write(1, "b", 1);
    4. putchar('a');
    5. write(1, "b", 1);
    6. putchar('a');
    7. write(1, "b", 1);
    8. }
    9. // 程序会打印:bbbaaa
    10. // 因为标准I/O打印的 a 会先放到缓冲区中,后面一次完成输出;

    4--原子操作

    原子操作:不可分割的操作;

    原子操作的作用:解决竞争与冲突;

    5--dup()和dup2()

    1. #include
    2. int dup(int oldfd);
    3. int dup2(int oldfd, int newfd); // 原子操作
    4. // dup 复制(准确来说,将当前文件描述符对于文件的权限共享过来给新的文件描述符了)当前的文件描述符
    5. // dup 返回一个新的文件描述符,新旧文件描述符共享访问同一个文件
    6. // dup 返回的新文件描述符一定是当前可用文件描述中的最小数值
    7. // dup2是原子操作,不能被打断,它会关闭旧的文件描述符
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define FNAME "./out"
    8. int main(){
    9. int fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
    10. if(fd < 0){
    11. perror("open()");
    12. exit(1);
    13. }
    14. // close(1); // 关闭标准输出
    15. // dup(fd); // 关闭标准输出后,1成了最小的可用文件描述符,因此dup(fd)后,1和最初的fd共享打开的文件
    16. dup2(fd, 1); // 原子操作,功能等同于上面两句
    17. if(fd != 1){
    18. close(fd);
    19. }
    20. // 上面语句的功能相当于是将文件描述符1映射到打开的文件,即打开文件的文件描述符 fd = 1
    21. // puts默认打印到标准输出,但此时标准输出被关闭了
    22. // 文件描述符1其实指向的是打开的文件,因此puts打印到了打开的文件里
    23. puts("hello!");
    24. exit(0);
    25. }

    6--fcntl()和ioctl()

    1. #include
    2. #include
    3. int fcntl(int fd, int cmd, ... /* arg */ );
    4. // fcntl() performs one of the operations described below on the open file descriptor fd.
    5. // The operation is determined by cmd.
    6. // fcntl() 根据提供的 cmd 来对输入的 fd 进行相关操作
    1. #include
    2. int ioctl(int fd, unsigned long request, ...);
    3. // ioctl 是设备驱动程序中设备控制接口函数
    4. // 一个字符设备驱动通常会实现设备打开、关闭、读、写等功能
    5. // 在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。

  • 相关阅读:
    开源在医疗健康领域的应用
    DGUS新升级:全面支持数字视频播放功能
    C/C++test——高效完成白盒测试
    查询企业联系方式的途径有哪些?
    EMQX URL NOT found
    【torchvision】torchvision 介绍
    如何监控文件已成功通过EDI系统发给客户(三)-997回写
    pandas读取json文件,文件中包含多个json对象
    【Hack The Box】linux练习-- SwagShop
    VsCode 配置java环境(详细教程)
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/132784373