开发者学堂课程【物联网开发- Linux 高级程序设计全套视频:无名管道读写特点 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/660/detail/11028
无名管道读写特点
内容介绍
一、从管道中读写数据的特点
二、验证一
三、验证四
四、验证三
一、从管道中读写数据的特点
1、默认用read函数从管道中读数据是阻塞的
在读数据的过程中,若无名管道内无数据,就会停在读;待有数据后继续执行。
2、调用write函数向管道里写数据,当缓冲区已满时write也会阻塞。
当管道满了之后,就会停在当前的位置;有空间后继续执行
3、通信过程中,读端口全部关闭后,写进程向管道内写数据时,写进程会(收到SIGPIPE)退出
父进程创建一个子进程,若父子进程都将读端关闭,则没有进程在读东西。
编程时我们可以设置阻塞非阻塞(read默认阻塞,write也是阻塞的)
看一下其中的特点
编程时可通过fcntl函数设置文件的阻塞特性
设置为阻塞:
Fcntl(fd,F-setfl,0);
设置非阻塞:
Fcntl(fd,-setfl,O-NONBLOCK);
(将读端或者写端的文件描述符写入,NONBLOCK指非阻塞)
如果将读端设置为非阻塞,没有数据的时候也不会阻塞;
如果将写端设置为非阻塞,写满了就不能再写,但不会阻塞。
二、验证一
来看一个例子:
验证无名管道文件读写的阻塞和非阻塞
(我们只写一句话,之后不停的对此进行读取,如果没有数据,那么read就会带阻塞)
#include <stdio.h>
#include‹string.h>
#include<unistd.h>
#include‹stdlib.h>
#include <sys/twpes.h>
#include<sys/wait.h>
#include <fcntl.h>
注意需要包括以上图文件
int main (int argc, char *argv[])
int fd pipe[2];
首先我们定义一个数组,用来作为管道的读写端号
char buf[]=“hello world ”
(定义一个字符数组,存放hello world;注意 buf是12个字节,)
pid_t pid;
首先进来需要创建管道,然后管道的读端和写端保存在数组里面
if (pipe (fd pipe) < 0)
perror ("pipe") ;
pid=fork();(创建子进程)
if (pid< 0)
{
perror ("fork") ;
exit (-1);
}
if (pid==0)
{
Sleep(3);(3秒之后write)
write(fd_pipe[1],buf,strlen(buf)) ;(strlen测试写了多少个字节进去)
_exit (0) ;
}
else
{
//fcntl(fd_pipe[0],F_SETFL,O_NONBLOCK);
fcntl设置管道的读端,默认第三个数据传0是阻塞的
fcntl (fd pipe[0], F_SETFL, 0) ;
while (1)(循环)
{
memset (buf, 0, sizeof (buf)) ;(先清空buf)
read (fd pipe[0], buf,sizeof (buf) ) ;(从管道的读端开始读东西)
print ("buf=[%s] \n", buf) ;(3秒后读到数据打印出来)
sleep (1) ;
延时1秒再去读,但是子进程已经退出,父进程一直阻塞在read上
}
}
Return 0;
三、验证二
调用 write 函数向管道里写数据,当缓冲区已满时write也会阻塞(在管道中写数据,如果写满了write在阻塞)。
更改进程:
父进程只读一次(读到之后打印出来),在while循环上。
子进程while(1)在不断的输入内容,每写完一次都i++,printf(“i=%d\n”,d)
此管道早晚都会被子进程写满,写满之后write堵塞,i就不打印了。
四、验证三
通信过程中,读端口全部关闭后,写进程向管道内写数据时,写进程会(收到SIGPIPE)退出
更改进程:
父进程先去读一次数据,之后close(fd-pipe[0]);//关闭读端
子进程也需要关闭读端,之后循环write;一秒钟写一次;读不到数据就一直停在当前。
需要将所有的读端关掉