socket阻塞与非阻塞

转载 2015年11月20日 23:45:33

1. 设置阻塞和非阻塞

1) 获取文件的flags,即open函数的第二个参数:

       flags = fcntl(fd,F_GETFL,0);

2) 设置文件的flags:

      fcntl(fd,F_SETFL,flags);

3) 增加文件的某个flags,比如文件是阻塞的,想设置成非阻塞:

       flags = fcntl(fd,F_GETFL,0);

       flags |= O_NONBLOCK;

      fcntl(fd,F_SETFL,flags);

4) 取消文件的某个flags,比如文件是非阻塞的,想设置成为阻塞:

      flags = fcntl(fd,F_GETFL,0);

      flags &= ~O_NONBLOCK;

      fcntl(fd,F_SETFL,flags);



阻塞:

          在设计简单字符驱动程序时,要注意一个重要问题.

          当一个设备无法立刻满足用户的读写请求时应当如何处理?

          例如:调用 read 时没有数据可读,但以后可能会有;

          或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据.

          应用程序通常不关心这种问题,应用程序只是调用 read 或 write 并得到返回值.

          驱动程序应当 ( 缺省地 ) 阻塞进程使它进入睡眠直到请求可以得到满足.

阻塞操作:

          是指在执行设备操作时,若不能获得资源挂起进程直到满足可操作的条件后进行操作

          被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足.

非阻塞操作:

          进程不能进行设备操作时并不挂起,他或者放弃,或者不停的查询,直到可以进行操作为止.


阻塞方式-read- 实现:

          在阻塞型驱动程序中,read 实现方式如下:

          如果进程调用 read ,但设备 没有数据 或 数据不足进程阻塞.

          当新数据到达后,唤醒被阻塞进程.


阻塞方式-write- 实现:

          在阻塞型驱动程序中,write 实现方式如下:
          如果进程调用了 write ,但设备 没有足够的空间供其写入数据进程阻塞.
          当设备中的数据被读走后,缓冲区中空出部分空间,则唤醒进程.

非阻塞方式的读写操作:

          阻塞方式是文件读写操作的默认方式,但是应用程序员可通过使用O_NONBLOCK 标志来人为
          的设置读写操作为非阻塞方式 .( 该标志定义在 < linux/fcntl.h > 中,在打开文件时指定 ) .

          如果设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read ,
          或者在缓冲区没有空间时调用了 write ,系统只是简单的返回 -EAGAIN,而不会阻塞进程.

实例 --- 读阻塞的实现:

          
          

用 while 是因为可能别的信号唤醒了睡眠,我们要通过while 重新检测是否真有数据了....


          


实例 --- 按键驱动阻塞实现:

1,在 open 函数 查看看是 阻塞方式 还是 非阻塞方式:

         file 结构体中含有 f_flags 标志位,看是 阻塞方式 还是 非阻塞方式:
         O_NONBLOCK 为 非阻塞方式
  1. if (file->f_flags & O_NONBLOCK)  /* 非 阻塞操作 */  
  2. {  
  3.     if (down_trylock(&button_lock))   /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */  
  4.         return -EBUSY;  
  5. }  
  6. else                             /* 阻塞操作 */  
  7. {  
  8.     /* 获取信号量 */  
  9.     down(&button_lock);   /* 获取不到  睡眠 */  
  10. }  

2,在 read 函数中同样查看:

  1. if (file->f_flags & O_NONBLOCK)       /* 非 阻塞操作 */  
  2. {  
  3.     if (!ev_press)                 /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */  
  4.         return -EAGAIN;        /* 返回 -EAGAIN 让再次来执行 */  
  5. }  
  6. else                                   /* 阻塞操作 */  
  7. {  
  8.     /* 如果没有按键动作, 休眠 */  
  9.     wait_event_interruptible(button_waitq, ev_press);  
  10. }  

3,应用程序中:

1,以阻塞方式运行:

后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;
  1. int main(int argc, char **argv)  
  2. {  
  3.     unsigned char key_val;  
  4.     int Oflags;  
  5.                                                      
  6.     fd = open("/dev/buttons", O_RDWR );  
  7.     if (fd < 0)  
  8.     {  
  9.         printf("can't open!\n");  
  10.         return -1;  
  11.     }  
  12.   
  13.     while (1)  
  14.     {  
  15.         read(fd, &key_val, 1);  
  16.         printf("key_val: 0x%x\n", key_val);  
  17.     }  
  18.       
  19.     return 0;  
  20. }  


2,以非阻塞方式运行:

open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;
后台执行应用程序:
  1. int main(int argc, char **argv)  
  2. {  
  3.     unsigned char key_val;  
  4.     int ret;  
  5.     int Oflags;  
  6.   
  7.     fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);  
  8.     if (fd < 0)  
  9.     {  
  10.         printf("can't open!\n");  
  11.         return -1;  
  12.     }  
  13.   
  14.     while (1)  
  15.     {  
  16.         ret = read(fd, &key_val, 1);  
  17.         printf("key_val: 0x%x, ret = %d\n", key_val, ret);  
  18.         sleep(5);  
  19.     }  
  20.       
  21.     return 0;  
  22. }  

非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;



服务器编程心得(四)—— 如何将socket设置为非阻塞模式

1. windows平台上无论利用socket()函数还是WSASocket()函数创建的socket都是阻塞模式的: SOCKET WSAAPI socket( _In_ int af, ...
  • analogous_love
  • analogous_love
  • 2016年11月04日 13:11
  • 10158

非阻塞socket编程

一. 阻塞与非阻塞阻塞: 阻塞调用是指调用结果返回之前,当前线程会被挂起。该进程被标记为睡眠状态并被调度出去。函数只有在得到结果之后才会返回。当socket工作在阻塞模式的时候, 如果没有数据的情况下...
  • okiwilldoit
  • okiwilldoit
  • 2016年03月30日 15:39
  • 1065

socket阻塞与非阻塞模式

本文转载 http://blog.sina.com.cn/s/blog_63e164b00100mfvu.html 阻塞模式 Windows套接字在阻塞和非阻塞两...
  • yu_sn0w
  • yu_sn0w
  • 2015年11月27日 13:14
  • 1652

Socket 阻塞与非阻塞模式

阻塞模式 Windows套接字在阻塞和非阻塞两种模式下执行I/O操作。在阻塞模式下,在I/O操作完成前,执行的操作函数一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式...
  • liang08114
  • liang08114
  • 2016年02月17日 10:53
  • 2116

Linux socket非阻塞connect方法(一)

Linux非阻塞connect方法(linux non-blocking socket connect)
  • u011804580
  • u011804580
  • 2013年08月24日 15:11
  • 15828

阻塞与非阻塞socket的优缺点

http://www.cnblogs.com/sunada2005/p/3591378.html 谓阻塞方式的意思是指,当试图对该文件描述符进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进...
  • taotaoah
  • taotaoah
  • 2016年09月05日 16:53
  • 1689

socket非阻塞模式服务器设计与实现

阻塞和非阻塞的区别就是一个阻塞等待,一个直接返回,并返回一些有意义的错误代码。跳转到代码思路如下: 1.初始化套接字2.创建套接字3.设置socket为非阻塞模式int ioctlsocket( ...
  • qq_18297675
  • qq_18297675
  • 2016年11月14日 20:04
  • 769

java 非阻塞方式socket

package Test3;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuf...
  • bobbob32
  • bobbob32
  • 2017年06月29日 16:58
  • 278

如何设置linux socket为非阻塞

将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,即: 设置成非阻塞模式: 先用fcntl的F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK; ...
  • haoyu_linux
  • haoyu_linux
  • 2015年03月16日 15:27
  • 3401

从缓冲上看阻塞与非阻塞socket在发送接收上的区别

最近在网络上看到一些帖子以及回复,同时又搜索了一些网络上关于阻塞非阻塞区别的描述,发现很多人在描述两者的发送接收时操作返回以及缓冲区处理的区别时有不同程度的误解。所以我想写一篇文章来纠正错误,并作为记...
  • qq_14821541
  • qq_14821541
  • 2016年09月05日 12:05
  • 710
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:socket阻塞与非阻塞
举报原因:
原因补充:

(最多只允许输入30个字)