Linux内核(六)阻塞&非阻塞

Linux内核(六)阻塞&非阻塞,第1张

阻塞和非阻塞IO是访问设备的两种模式,驱动程序可以灵活的支持者两种用户空间对设备的访问方式。

如下图所示,在阻塞访问时,不能获取资源的进程将进入休眠,它将会让出CPU,因为阻塞的进程会进入休眠状态,所以必须要有一个动作能唤醒该进程,唤醒进程的地方最大的可能发生在中断里面,因为在硬件资源获得的同时往往伴随着一个中断。而非阻塞的进程则不断的尝试,直到可以进行IO。

在Linux驱动程序中,可以使用等待队列(Wait Queue)来实现阻塞队列的唤醒。等待队列以队列为基础数据结构,与进程调度机制紧密结合,可以用来同步对系统资源的访问,

读 *** 作

对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返

回。当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲

区中的数据大于期望读取的字节数时,读取期望读取的字节数,返回实际读取的长度。

对于非阻塞socket而言,socket的接收缓冲区中有没有数据,read调用都会立刻返回。接收缓冲区中有

数据时,与阻塞socket有数据的情况是一样的,如果接收缓冲区中没有数据,则返回错误号为

EWOULDBLOCK,

表示该 *** 作本来应该阻塞的,但是由于本socket为非阻塞的socket,因此立刻返回,遇到这样的情况,可

以在下次接着去尝试读取。如果返回值是其它负值,则表明读取错误。

因此,非阻塞的rea调用一般这样写:

if

((nread

=

read(sock_fd,

buffer,

len))

<

0)

{

if

(errno

==

EWOULDBLOCK)

{

return

0

//表示没有读到数据

}else

return

-1

//表示读取失败

}else

return

nread读到数据长度

写 *** 作

对于写 *** 作write,原理是类似的,非阻塞socket在发送缓冲区没有空间时会直接返回错误号EWOULDBLOCK,

表示没有空间可写数据,如果错误号是别的值,则表明发送失败。如果发送缓冲区中有足够空间或者

是不足以拷贝所有待发送数据的空间的话,则拷贝前面N个能够容纳的数据,返回实际拷贝的字节数。

而对于阻塞Socket而言,如果发送缓冲区没有空间或者空间不足的话,write *** 作会直接阻塞住,如果有

足够空间,则拷贝所有数据到发送缓冲区,然后返回.

非阻塞的write *** 作一般写法是:

int

write_pos

=

0

int

nLeft

=

nLen

while

(nLeft

>

0)

{

int

nWrite

=

0

if

((nWrite

=

write(sock_fd,

data

+

write_pos,

nLeft))

<=

0)

{

if

(errno

==

EWOULDBLOCK)

{

nWrite

=

0

}else

return

-1

//表示写失败

}

nLeft

-=

nWrite

write_pos

+=

nWrite

}

return

nLen

建立连接

阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则

connect

返回.否则的话一直阻塞.

非阻塞方式,connect将启用TCP协议的三次握手,但是connect函数并不等待连接建立好才返回,而是

立即返回。返回的错误码为EINPROGRESS,表示正在进行某种过程.

接收连接

对于阻塞方式的倾听socket,accept在连接队列中没有建立好的连接时将阻塞,直到有可用的连接,才返

回。

非阻塞倾听socket,在有没有连接时都立即返回,没有连接时,返回的错误码为EWOULDBLOCK,表示本来应

该阻塞。

无阻塞的设置方法

方法一:fcntl

int

flag

if

(flag

=

fcntl(fd,

F_GETFL,

0)

<0)

perror("get

flag")

flag

|=

O_NONBLOCK

if

(fcntl(fd,

F_SETFL,

flag)

<

0)

perror("set

flag")

方法二:ioctl

int

b_on

=

1

ioctl

(fd,

FIONBIO,

&b_on)


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7602930.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-07
下一篇 2023-04-07

发表评论

登录后才能评论

评论列表(0条)

保存