• 网络编程:阻塞IO和非阻塞IO(fcntl函数说明)


    一 阻塞IO

    1.1概念:

    阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。

    缺省情况下,套接字建立后所处于的模式就是阻塞I/O 模式。

    前面学习的很多读写函数在调用过程中会发生阻塞。

    读操作中的read、recv、recvfrom

    写操作中的write、send

    其他操作:accept、connect

    以读阻塞为例:

    当进程执行到读函数的时候

    如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,

    如果缓冲区里面没有内容,进程就会进入休眠态,直到缓冲区里面有内容了

    内核会唤醒该进程,然后进程过来读取缓冲区的内容,然后继续向下执行。

    写操作也是会阻塞的,当写缓冲区满的时候就会阻塞

    1.2代码实现:

    1.2.1读端

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(){
    8. int fd1 = open("./fifo1", O_RDONLY);
    9. int fd2 = open("./fifo2", O_RDONLY);
    10. int fd3 = open("./fifo3", O_RDONLY);
    11. char buff1[128] = {0};
    12. char buff2[128] = {0};
    13. char buff3[128] = {0};
    14. while(1){
    15. memset(buff1, 0, 128);
    16. read(fd1, buff1, 128);
    17. printf("buff1:[%s]\n", buff1);
    18. memset(buff2, 0, 128);
    19. read(fd2, buff2, 128);
    20. printf("buff2:[%s]\n", buff2);
    21. memset(buff3, 0, 128);
    22. read(fd3, buff3, 128);
    23. printf("buff3:[%s]\n", buff3);
    24. }
    25. close(fd1);
    26. close(fd2);
    27. close(fd3);
    28. return 0;
    29. }

    1.2.2写端(三个写端都是一样的,只不过名字不一样)

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(){
    8. int fd = open("./fifo1", O_WRONLY);
    9. char buff[128] = {0};
    10. while(1){
    11. memset(buff, 0, 128);
    12. fgets(buff, 128, stdin);
    13. buff[strlen(buff)-1] = '\0';
    14. write(fd, buff, 128);
    15. }
    16. close(fd);
    17. return 0;
    18. }

    二非阻塞IO

    2.1概念

    以读阻塞为例:

    当进程执行到读函数的时候

    如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,

    如果缓冲区里面没有内容,进程就不进入休眠态,而是立即返回一个错误

    这种情况下就需要我们轮询去执行操作,这种操作是十分占用CPU的

    一般不推荐使用

    一般阻塞函数都有一个能设置非阻塞方式的选项

    如 recv 和 recvfrom 的 MSG_DONTWAIT

    waitpid 的 WNOHONG

    O_NONBLOCK

    对于read这种函数,本身是没有非阻塞选项的,这是可以使用 fcntl 函数来设置非阻塞

    2.2fcntl函数的说明:

    1. int flag = fcntl(fd, F_GETFL);//获取原来的状态
    2. flag |= O_NONBLOCK;//添加非阻塞属性
    3. fcntl(fd, F_SETFL, flag);//再设置回去

    2.3代码说明:

    2.3.1读端:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(){
    8. int fd1 = open("./fifo1", O_RDONLY);
    9. int fd2 = open("./fifo2", O_RDONLY);
    10. int fd3 = open("./fifo3", O_RDONLY);
    11. char buff1[128] = {0};
    12. char buff2[128] = {0};
    13. char buff3[128] = {0};
    14. //将文件描述符都设置成非阻塞
    15. int flag = fcntl(fd1, F_GETFL);
    16. flag |= O_NONBLOCK;
    17. fcntl(fd1, F_SETFL, flag);
    18. flag = fcntl(fd2, F_GETFL);
    19. flag |= O_NONBLOCK;
    20. fcntl(fd2, F_SETFL, flag);
    21. flag = fcntl(fd3, F_GETFL);
    22. flag |= O_NONBLOCK;
    23. fcntl(fd3, F_SETFL, flag);
    24. while(1){
    25. memset(buff1, 0, 128);
    26. read(fd1, buff1, 128);
    27. printf("buff1:[%s]\n", buff1);
    28. memset(buff2, 0, 128);
    29. read(fd2, buff2, 128);
    30. printf("buff2:[%s]\n", buff2);
    31. memset(buff3, 0, 128);
    32. read(fd3, buff3, 128);
    33. printf("buff3:[%s]\n", buff3);
    34. //sleep(1);//此处的sleep(1) 是为了防止刷屏
    35. //能看到现象的,正常应该是没有的
    36. //如果没有这个sleep 使用 top可以看到
    37. //该进程 基本已经把CPU占满了
    38. }
    39. close(fd1);
    40. close(fd2);
    41. close(fd3);
    42. return 0;
    43. }

    2.3.2写端和上面一样

  • 相关阅读:
    国庆值得入手的蓝牙耳机哪款好?入耳式蓝牙耳机推荐
    Linux shell编程基础
    chatGPT的前世今生
    地图:leaflet基本使用
    8/11 二分图染色+KM算法变型+后缀数组+图论
    SuperMap iServer 全局设置使用
    深入理解Java虚拟机(第3版)学习笔记——线程安全与锁优化(超详细)
    电脑重装系统后桌面图标如何调小尺寸
    基于springboot的房屋租赁系统
    gorm的使用(持续更新)
  • 原文地址:https://blog.csdn.net/a2998658795/article/details/126442470