我是靠谱客的博主 帅气可乐,最近开发中收集的这篇文章主要介绍linux系统中管道的介绍和线程同步代码示例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

传统的进程间通信其中有无名管道(PIPE)、有名管道(FIFO)和信号(Signal)。咱们今天就说说linux中基于POSIX的有名管道(FIFO)和无名管道(PIPE)。

1. 描述:

管道提供一个单向的进程间通讯通道。一个管道,有一个读端和一个写端。写到写端的数据能从这个管道的读端读出。

无名管道,在linux中可以通过pipe2函数来创建一个无名管道,执行这个函数后,会返回两个文件描述符,一个指向管道的读端,一个指向管道的写端。无名管道用于有亲缘关系的进程之间通信。通信方式类似半双工通信方式。

有名管道(先进先出的缩写),在linux文件系统内有一个名字(区别无名管道),可以通过mkfifo函数来创建一个有名管道。任何进程都可以通过open函数来打开一个有名管道文件,前提是这个进程有打开权限。读端使用open函数打开的标识是O_RDONLY;写端在open函数中使用O_WRONLY来打开。用于任何进程之间的通信。

注意:

0)尽管一个有名管道在文件系统中有一个名字,但是对于隐藏设备,管道的I/O操作不起作用。

1)有名管道和无名管道的不同就在他们的创建和打开的方式上。一旦创建和打开任务已经完成,那么有名管道和无名管道的I/O操作意义完全相同。

2)管道提供的通讯通道是字节流:没有消息边界的概念。

3)不能使用lseek函数来操作管道。

4)在使用fork创建子进程的时候,要注意适当合理的使用close关闭子进程从父进程继承拷贝的多余的读端或者是写端的文件描述符。

5)管道中的数据从读端读走了,就从管道中消失了。

2. 规则:

1. 读(读端写端都存在):如果一个进程读一个空管道,read函数会阻塞,直到管道中有可用数据。

2. 写(读端写端都存在):如果一个进程想写一个已满管道,write函数会阻塞,直到管道中有足够的数据被读出来让write函数完成写操作。

如果想让读写不阻塞,可以参考fcntl函数。使用F_SETFL和O_NONBLOCK来完成。

3. 读(写端全部关闭):如果指向写端的所有文件描述符都被关闭,read函数对该管道读的尝试结果会返回0;

4. 写(读端全部关闭):如果指向读端的所有文件描述符都被关闭,write函数对该管道的写操作会产生SIGPIPE信号,并发送给调用write函数的进程;如果调用write的进程忽略了SIFPIPE信号,那write会带着EPIPE的错误而失败。

管道中的数据可读性只有一次。也就是说数据在管道中阅后即焚。管道中的数据读了就没有了。

(1) 无名管道:int pipe(int pipefd[2]);

参数:

//pipefd 获得操作管道的文件描述符 ,读:pipefd[0],写:pipefd[1]。

返回值: 成功返回0,失败返回-1

(2)创建有名管道文件

int mkfifo(const char *pathname, mode_t mode);

@pathname 管道文件名

@mode 指定文件的权限

返回值:

成功返回0,失败返回-1

下面以两个线程中使用有名管道的同步通信为例,展示相关代码的使用:

#include

#include

//strlen memset

#include

//mkfifo open

#include

#include

//open

#include

//read

#include

//errno

#include

//pthrea_mutex_unlock

#include

//sem_init sem_wait sem_post

#include

#define N 1024//缓存buf的大小

sem_t read_sem;//读信号资源

sem_t write_sem;//写信号资源

void *read_fifo(void* args){//读管道线程的线程主体

int ret = -1;

int fd_r = -1;

char buf[N] = {0};

ssize_t num = 0;

ret = mkfifo((char*)args,0666);

if(ret < 0 && errno != EEXIST){

perror("read_fifo mkfifo failed");

return (char*)args;

}

fd_r = open((char*)args,O_RDONLY|O_NONBLOCK,0666);/*非阻塞方式打开文件获取文件描述符*/

if(fd_r < 0){

perror("read_fifo open failed");

return (char*)args;

}

while(1)

{

sem_wait(&read_sem);/*读管道线程获取读管道的资源,实现和写线程的同步*/

memset(buf,0,sizeof(buf));/*清空缓冲区*/

num = read(fd_r,buf,sizeof(buf));

buf[N-1] = '';/*输出前的防止越界操作*/

if(num > 0){

printf("%d read:%sn",num,buf);

}

if(strncmp(buf,"q",1) == 0){/*对退出字符串的捕捉*/

close(fd_r);

sem_post(&write_sem);

break;

}

sem_post(&write_sem);/*释放写操作资源*/

}

close(fd_r);

return (char*)args;

}

void *write_fifo(void* args){

int ret = -1;

int fd_w = -1;

char buf[N] = {0};

ssize_t num = 0;

ret = mkfifo((char*)args,0666);

if(ret < 0 && errno != EEXIST){//排除已经创建管道的错误退出情况

perror("read_fifo mkfifo failed");

return (char*)args;

}

fd_w = open((char*)args,O_WRONLY|O_NONBLOCK,0666);

if(fd_w < 0){

perror("read_fifo open failed");

return (char*)args;

}

while(1)

{

sem_wait(&write_sem);

printf("#:");/*输入提示符*/

fgets(buf,sizeof(buf),stdin);

buf[strlen(buf) - 1] = '';/*对fgets获取到终端的’n’字符的消除*/

num = write(fd_w,buf,strlen(buf));

if(strncmp(buf,"q",1) == 0){

close(fd_w);

sem_post(&read_sem);

break;

}

sem_post(&read_sem);

}

close(fd_w);

return (char*)args;

}

int main(int argc, const char *argv[])

{

int ret_p = -1;

pthread_t tid[2] = {0};

sem_init(&read_sem,0,0);/*程序启动时,管道没有资源,故读的资源要初始化为0*/

sem_init(&write_sem,0,1);/*程序启动时,管道首先需要一个写操作,故写资源为1*/

if(argc < 2){/*程序运行时,紧跟其后的输入参数判断*/

perror("Input wrong format");

puts("Excuting_code_name + new_fifoname");

exit(EXIT_SUCCESS);

}

ret_p = pthread_create(&tid[0],NULL,read_fifo,(char*)argv[1]);/*把在程序后的参数传递给相关进程作为有名管道文件的文件名*/

if(ret_p < 0){

perror("read_fifo pthread_create failed");

exit(EXIT_FAILURE);

}

#if 1

ret_p = pthread_create(&tid[1],NULL,write_fifo,(char*)argv[1]);

if(ret_p < 0){

perror("write_fifo pthread_create failed");

exit(EXIT_FAILURE);

}

#endif

pthread_join(tid[0],NULL);/*线程的阻塞回收,亦可以防止主进程结束*/

pthread_join(tid[1],NULL);

return 0;

}

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,

差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。(点击找小助理领取)

 

最后

以上就是帅气可乐为你收集整理的linux系统中管道的介绍和线程同步代码示例的全部内容,希望文章能够帮你解决linux系统中管道的介绍和线程同步代码示例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部