-
2021-05-13 21:52:56
linux 线程或进程之间通过管道通信(pipe)
线程间通信:
#include // printf
#include // exit
#include // pipe
#include // strlen
#include // pthread_create
using namespace std;
void *func(void * fd)
{
printf("write fd = %d\n", *(int*)fd);
char str[] = "hello everyone!";
write( *(int*)fd, str, strlen(str) );
}
int main()
{
int fd[2];
char readbuf[1024];
if(pipe(fd) < 0)
{
printf("pipe error!\n");
}
// create a new thread
pthread_t tid = 0;
pthread_create(&tid, NULL, func, &fd[1]);
pthread_join(tid, NULL);
sleep(3);
// read buf from child thread
read( fd[0], readbuf, sizeof(readbuf) );
printf("read buf = %s\n", readbuf);
return 0;
}// 输出结果write fd = 4
read buf = hello everyone!�
进程间通信:
#include // printf
#include // exit
#include // pipe
#include // strlen
#include // pthread_create
using namespace std;
int main()
{
int fd[2];
int pid = 0;
char str[] = "hello";
char readbuf[1024];
if(pipe(fd) < 0)
{
printf("pipe error!\n");
}
if((pid = fork()) < 0)
{
printf("fork error!\n");
}
else if(pid == 0)
{
printf("child process!\n");
// close read channel
close(fd[0]);
write(fd[1], str, strlen(str));
}
else
{
printf("father process!\n");
// close write channel
close(fd[1]);
read(fd[0], readbuf, sizeof(readbuf));
printf("readbuf = %s\n", readbuf);
}
return 0;
}// 输出结果:father process!
child process!
readbuf = hello
更多相关内容 -
Linux Socket + pthread + pipe 实现socket通信和多线程数据共享
2020-09-05 18:19:28Linux Socket + pthread + pipe 实现socket通信和多线程数据共享 大道至简,基础的东西不能忘,对于网路时代,开发应该都跑不了socket,作为一个基本功,也好久没写写,简单了一个复习下。主要目标复习下socket的...Linux Socket + pthread + pipe 实现socket通信和多线程数据共享
大道至简,基础的东西不能忘,对于网路时代,开发应该都跑不了socket,作为一个基本功,也好久没写写,简单了一个复习下。主要目标复习下socket的同时,复习下linux多线程处理
涉及知识点:
1,socket
2,linux pthread使用
3,信号量(semaphore)、锁(mutex)、管道(pipe)、条件
更多知识点,百度应该比较多了。
代码逻辑:
1,server:最大支持10个链接,当收到有效连接时启动一个线程用于处理对于事务(recvfromClient)
在线程中如果收到client发送字符串vote则触发另一个线程votepthread来通知(voteAction)policethread线程vote事件发生了(policeCenter)
2,client:相对简单就是支持循环输入
话不多说,代码如下:
server代码:#include <iostream> #include <string> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <pthread.h> #include <unistd.h> #include <semaphore.h> using namespace std; sem_t sem; pthread_cond_t cond; pthread_mutex_t mutex; int pipeHandle[2]; void *voteAction(void *data) { while(1) { pthread_cond_wait(&cond, &mutex); pthread_t pid = pthread_self(); cout <<"people "<< pid <<" vote action happen, please call 911" << endl; write(pipeHandle[1], &pid, sizeof(pthread_t)); sem_post(&sem); } return NULL; } void *policeCenter(void* data) { while(1) { sem_wait(&sem); pthread_t senderId; read(pipeHandle[0],&senderId, sizeof(pthread_t)); cout << "911 center recevice people "<< senderId <<" notify vote event happened" << endl; } return NULL; } void *recvfromClient(void *data) { int connfd = (int)(*((int *)data)); char buff[1024]; while (1) { memset(buff, 0, sizeof(buff)); int ret = recv(connfd, buff, sizeof(buff), 0); if (ret == -1) { cout << "socket recv data fail" << endl; break; } if (string(buff) == "vote") { pthread_cond_signal(&cond); } cout << "server recv data:" << buff << endl; } close(connfd); pthread_exit(NULL); return NULL; } int main() { int socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 0 : 采用type默认的protocol if (socketfd == -1) { cout << "socket create fail" << endl; return -1; } struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(6666); if (bind(socketfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { cout << "socker bind fail" << endl; return -1; } if (listen(socketfd, 10) == -1) { cout << "socket listen fail" << endl; return -1; } // thread for vote pthread_t voteThread; int ret = pthread_create(&voteThread, NULL, voteAction, NULL); if (ret < 0) { cout << "create vote thread fail" << endl; close(socketfd); return -1; } pthread_cond_init(&cond, NULL); pthread_mutex_init(&mutex, NULL); pthread_t policeThread; ret = pthread_create(&policeThread, NULL, policeCenter, NULL); if (ret < 0) { cout << "create police center thread fail" << endl; //pthread_cance(voteThread); close(socketfd); return -1; } sem_init(&sem, 1, 0); //init pipe for share data between different threads ret = pipe(pipeHandle); if (ret < 0) { cout << "create pipe fail" << endl; close(socketfd); return -1; } cout << "server ready..." << endl; while(1) { int connfd = accept(socketfd, (struct sockaddr *)NULL, NULL); if (connfd == -1) { cout << "socket accept fail" << endl; continue; } pthread_t thread; int ret = pthread_create(&thread, NULL, recvfromClient, &connfd); if (ret < 0) { cout << "thread create fail" << endl; continue; } ret = pthread_detach(thread); if (ret < 0) { cout << "thread deatch fail" << endl; } } pthread_join(voteThread, NULL); pthread_join(policeThread, NULL); close(socketfd); return 0; }
client代码如下:
#include <iostream> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <netinet/in.h> using namespace std; int main() { int socketfd = socket(AF_INET, SOCK_STREAM, 0); if (socketfd == -1) { cout << "socket create fail" << endl; return -1; } struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(6666); int ret = connect(socketfd, (struct sockaddr*)&addr, sizeof(addr)); if (ret < 0) { cout << "socket connect fail" << endl; close(socketfd); return -1; } while(1) { cout << "Please input the data:"; string input; cin >> input; if (input.size() && send(socketfd, input.c_str(), input.size(), 0) < 0) { cout << "send msg fail" << endl; } } close(socketfd); return -1; }
编译
g++ server.cpp -lpthread -o server
g++ client.cpp -lpthread -o client -
linux下线程之间pipe通信c++练习
2020-04-22 23:46:49首先是用pipe在主线程和子线程通信,而且read是阻塞的 #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> typedef struct __...首先是用pipe在主线程和子线程通信,而且read是阻塞的
#include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> typedef struct __Thread { pthread_t tid; //thread id int notifyReceiveFd; //the receive side of pipe int notifySendFd; //the send side pf pipe } Thread; Thread* m_thread; void* work_thread(void* argc) { Thread* param=(Thread*) argc; printf("childthread_id=%lu\n",param->tid); int contant=0; printf("childthread--read return %ld\n",read(param->notifyReceiveFd, &contant, sizeof(int))); printf("childthread--read from pipe %d\n", contant); sleep(5); contant=100; //printf("childthread--write return %ld\n", write(param->notifySendFd, &contant, sizeof(int))); } int main(int argc, char** argv) { //build pipe between main-thread and child-thread m_thread = new Thread; int fds[2]; if(pipe(fds)) { perror("create pipe fds_1 error\n"); } int fds_1[2]; if(pipe(fds_1)) { perror("create pipe fds_1 error\n"); } m_thread->notifyReceiveFd=fds[0]; m_thread->notifySendFd=fds_1[1]; pthread_t id; pthread_create(&(m_thread->tid),NULL,work_thread,(void*)m_thread); printf("mainthread--childthread id is %lu\n",m_thread->tid); int contant = 1; printf("mainthread--write %d to pipe\n",contant); printf("mainthread--write return %ld\n", write(fds[1], &contant, sizeof(int))); //下面的read()函数会阻塞,因为没有给fds_1管道写入数据(把work_thread中注释掉的write那行去掉注释,则read()就可以读到数据而不阻塞) printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int))); printf("mainthread--read from pipe %d\n", contant); pthread_join(m_thread->tid,NULL); close(fds[0]); close(fds[1]); close(fds_1[0]); close(fds_1[1]); }
上面的代码会被阻塞,若要不阻塞运行,则要把文件描述符设置为非阻塞的,则read会立即返回(当管道没有数据可读时返回-1)
fcntl(fds_1[0], F_SETFL, O_NONBLOCK); //在read前,用fcnl设置fds_1[0]为非阻塞的 printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int)));
如要设置超时,可以使用select或poll,下面代码只举例select。更多相关知识可以参考这篇文章
#include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> typedef struct __Thread { pthread_t tid; //thread id int notifyReceiveFd; //the receive side of pipe int notifySendFd; //the send side pf pipe } Thread; Thread* m_thread; void* work_thread(void* argc) { Thread* param=(Thread*) argc; printf("childthread_id=%lu\n",param->tid); int contant=0; printf("childthread--read return %ld\n",read(param->notifyReceiveFd, &contant, sizeof(int))); printf("childthread--read from pipe %d\n", contant); sleep(5); contant=100; //printf("childthread--write return %ld\n", write(param->notifySendFd, &contant, sizeof(int))); } int main(int argc, char** argv) { //build pipe between main-thread and child-thread m_thread = new Thread; int fds[2]; if(pipe(fds)) { perror("create pipe fds_1 error\n"); } int fds_1[2]; if(pipe(fds_1)) { perror("create pipe fds_1 error\n"); } m_thread->notifyReceiveFd=fds[0]; m_thread->notifySendFd=fds_1[1]; pthread_t id; pthread_create(&(m_thread->tid),NULL,work_thread,(void*)m_thread); printf("mainthread--childthread id is %lu\n",m_thread->tid); int contant = 1; printf("mainthread--write %d to pipe\n",contant); printf("mainthread--write return %ld\n", write(fds[1], &contant, sizeof(int))); fd_set m_fds; FD_ZERO(&m_fds); FD_SET(fds_1[0], &m_fds); struct timeval t = {10, 0}; select(fds_1[0] + 1, &m_fds, NULL, NULL, &t); //若10后内fds_1[0]不可读则停止阻塞,程序继续往下走;如果把work_thread中的write那行去掉注释, //则注释到write执行完毕,因为我write前sleep了5s,所以我这里会阻塞5s,然后程序继续往下走 printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int))); printf("mainthread--read from pipe %d\n", contant); pthread_join(m_thread->tid,NULL); close(fds[0]); close(fds[1]); close(fds_1[0]); close(fds_1[1]); }
-
linux下多线程通信(一)
2018-09-21 20:11:57在linux下进行多线程编程,肯定会涉及到线程通信问题,本文主要分析pipe,即管道在多线之间通信实现。 #include&amp;amp;amp;lt;unistd.h&amp;amp;amp;gt; int pipe(int filedes[2]); 返回值:成功...在linux下进行多线程编程,肯定会涉及到线程通信问题,本文主要分析pipe,即管道在多线之间通信实现。
#include<unistd.h>
int pipe(int filedes[2]);
返回值:成功,返回0,否则返回-1。
参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道两个线程之间通信简单实现,单向pipe_1.c
源码地址:https://github.com/jeremy505/multi-thread-communication#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> Thread *m_Threads; static int threadcount = 1; void* work_thread(void* argc) { Thread* param = (Thread*) argc; printf("childthread_tid=%lu\n", param->tid); int contant = 0; //sleep(2); printf("childthread--read return %d\n",read(param->notifyReceiveFd, &contant, sizeof(int))); printf("childthread--read from pipe %d\n", contant); } int main(int argc, char** argv) { //在主线程和子线程之间建立管道 m_Threads = malloc(sizeof(Thread) * threadcount); int fds[2]; if( pipe(fds) ) { perror("create pipe error"); } m_Threads[0].notifyReceiveFd = fds[0]; pthread_create(&m_Threads[0].tid, NULL, work_thread, (void*)&m_Threads[0]); printf("mainthread_tid=%lu\n", m_Threads[0].tid); int contant = 1; // sleep(2); printf("mainthread--write %d to pipe\n", contant); printf("mainthread--write return %d\n",write(fds[1], &contant, sizeof(int))); pthread_join(m_Threads[0].tid, NULL); close(fds[0]); close(fds[1]); return 0; }
以上只是单向通信,即主线程向子线程写int型值1,子线程读到int型值1.
输出见下:
可见,输出与设想的一致,只是此时通信只是单向,如果要实现双向,最简单的办法就是再创建一组pipe,实现pipe_1_d.c如下:#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> typedef struct __Thread { pthread_t tid; //线程的ID int notifyReceiveFd; //管道的接收端 int notifySendFd; //管道的发送端 }Thread; Thread *m_Threads; static int threadcount = 1; void* work_thread(void* argc) { Thread* param = (Thread*) argc; printf("childthread_tid=%lu\n", param->tid); int contant = 0; //sleep(2); printf("childthread--read return %d\n",read(param->notifyReceiveFd, &contant, sizeof(int))); printf("childthread--read from pipe %d\n", contant); contant = 2; printf("childthread--write %d to pipe\n", contant); printf("childthread--write return %d\n",write(param->notifySendFd, &contant, sizeof(int))); } int main(int argc, char** argv) { //在主线程和子线程之间建立管道 m_Threads = malloc(sizeof(Thread) * threadcount); int fds[2]; if( pipe(fds) ) { perror("create pipe fds error"); } int fds_1[2]; if( pipe(fds_1) ) { perror("create pipe fds_1 error"); } m_Threads[0].notifyReceiveFd = fds[0]; m_Threads[0].notifySendFd = fds_1[1]; pthread_create(&m_Threads[0].tid, NULL, work_thread, (void*)&m_Threads[0]); printf("mainthread_tid=%lu\n", m_Threads[0].tid); int contant = 1; // sleep(2); printf("mainthread--write %d to pipe\n", contant); printf("mainthread--write return %d\n",write(fds[1], &contant, sizeof(int))); printf("mainthread--read return %d\n",read(fds_1[0], &contant, sizeof(int))); printf("mainthread--read from pipe %d\n", contant); pthread_join(m_Threads[0].tid, NULL); close(fds[0]); close(fds[1]); close(fds_1[0]); close(fds_1[1]); }
另外创建一组pipe,主线读,子线程写。主线程先写1,然后阻塞等待子线程网管道中写值,子线程通过管道读到1之后往管道写2,此时管道有数据,主线程读取值2,输出如下:
以上只是简单的通过pipe线程之间进行同行,注意到读写都是阻塞的。如果不希望线程使用阻塞方式,一般会设置管道文件描述符为非阻塞,然后借助epoll或者select监听管道文件描述符读写事件。
线程之间通过pipe通信也可以应用到进程之间,在使用fork之后,管道描述符被拷贝了一份,所以父子进程必须关闭其中之一,假设父进程关闭读[close(fd[0])],子进程就要关闭写[close(fd[1])],,实现单向通信,反过来也是一样.
进程之间的通信,推荐一种方式使用共享内存,共享内存区是最快的IPC形式,此种方式也可在两个完全独立的程序之间进行数据传递,后续再详细介绍。
当然,进程以及线程之间的通信不止以上方法,还有使用socket,eventfd等。 -
Linux服务器多线程编程
2022-03-21 22:00:37Linux多线程服务器开发笔记 第三章-----多线程服务器适用场合与常用编程模型 目录Linux多线程服务器开发笔记前言一、进程与线程二、使用步骤1.引入库2.读入数据总结 前言 本文记录了我阅读《Linux多线程编程》的... -
LINUX多线程pipeline架构的创建分析
2021-05-12 14:10:08POSIX多线程的使用方式中,有一种很重要的方式-----流水线(亦称为“管道”)方式,“数据元素”流串行地被一组线程按顺序执行。它的使用架构可参考下图: 以面向对象的思想去理解,整个流水线,可以理解为一个数据... -
linux 管道 线程同步,该如何解决
2021-05-13 20:59:32linux 管道 线程同步各位,最近想使用管道来实现线程同步,出现一个问题,百思不得其解,望各位大侠指点一二...先贴上代码:#include#include#include#include#include#include#includeintpip[]={-1,-1};voidsleep_... -
Linux的进程线程及调度
2020-07-10 10:46:39Linux的进程线程及调度 本文为宋宝华《Linux的进程、线程以及调度》学习笔记。 1 进程概念 1.1 进程与线程的定义 操作系统中的经典定义: 进程:资源分配单位。 线程:调度单位。 操作系统中用PCB(Process ... -
Linux下实现多线程异步管道
2020-08-04 12:36:06目录 架构 代码 相关阅读 “最近在做F-Stack相关内容,F-Stack协议栈单线程独占.../*主循环,由主进程执行 */ } 相关阅读 《Linux异步管道多线程速率测试》https://rtoax.blog.csdn.net/article/details/107812606 -
Linux 多线程和多进程的区别(小结)
2018-11-06 16:21:34很想写点关于多进程和多线程的东西,我确实很爱他们。但是每每想动手写点关于他们的东西,却总是求全心理作祟,始终动不了手。 今天终于下了决心,写点东西,以后可以再修修补补也无妨。一.为何需要多进程(或者多... -
操作系统原理:C语言 threads多线程 + Pipe管道 实现单机聊天系统
2020-04-24 13:26:13在程序中会涉及到3个文件,2个管道,2个进程,4个线程。线程之间的拓扑图如下: 【完整代码附在文章最后】 1.创建连通管道 首先创建fifo_create.c文件来事先创建2个管道,分别为A发送B接收、A接收B发送。使用... -
修改linux系统用户最大线程数限制
2021-05-14 02:29:44javatomcat启动后总是报错:java.lang.OutOfMemoryError: unable to create new native thread,linux刚开始觉得内存不够就增长tomcat内存:centosJAVA_OPTS="-server -XX:PermSize=1024M -XX:MaxPermSize=2048m -... -
Linux进程间通信-线程间通信
2021-05-08 23:29:12Linux作为一种新兴的操作系统,几乎支持所有的Unix下常用的进程间通信方法:管道、消息队列、共享内存、信号量、套接口。1、管道管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘... -
linux下多线程由于SIGPIPE退出进程的分析。
2016-10-26 15:37:19tcp协议是全双工的,这就可以看成是两条单工信道,单工信道是管道PIPE,在对端调用close后,对端将发送一个FIN标志给本端,在本端进行read返回0的话,就表示对端关闭了对端负责的一条管道,但是本端这一条管道还可以... -
linux查看cpu个数,线程数及cpu型号
2021-05-14 11:49:01修改linux系统用户最大线程数限制 linux系统对线程数量有个最大限制,当达到系统限制的最大线程数时使用账号密码ssh到系统时是无法登陆的,会报Write failed: Broken pipe,或者是shell request fa ... 随机推荐 ... -
Linux的进程/线程间通信方式总结
2021-05-10 05:55:17Linux系统中的进程间通信方式主要以下几种:同一主机上的进程通信方式* UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal)* System V进程通信方式:包括信号量(Semaphore), 消息队列(Message ... -
Linux 多进程多线程编程
2018-03-20 21:50:05消息队列是内核地址空间中的内部链表,通过Linux内核在各个进程之间传送内容,每个消息队列可以用IPC标识符位移地进行确认。不同的消息队列之间相互独立,每个消息队列中的消息,又构成一个独立的链表。 消息缓冲... -
libevent+多线程+pipe的死锁问题
2021-11-17 00:12:07libevent+多线程+pipe的死锁问题 每个线程都是一个libevent实例。线程间通信使用的是管道机制,在写端调用write()时,直接写入8个字节的消息指针。读端调用read()时,每次读取8个字节。 现有A、B、C三个线程,C线程... -
Linux的进程/线程通信方式总结
2021-05-08 23:28:58Linux系统中的进程通信方式主要以下几种:同一主机上的进程通信方式* UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal)* System V进程通信方式:包括信号量(Semaphore), 消息队列(Message Queue)... -
Linux 系统开启最大线程数 调优
2021-05-11 10:18:57系统最大线程数说明系统可开启的最大线程数,可根据系统本身负载配置进行调优。查看系统最大线程数1、查看系统开启的最大线程数。ulimit -u[root@izbp1brwu1w35r1dmj8ykcz html]# ulimit -u31215输出结果2、查系统... -
(真正全)Linux进程和线程的基本编程、通讯和例程【杂记】
2022-04-14 13:16:22真正的全面!对 Linux 进程 和 线程 的基本 编程、通讯(IPC、线程同步) 和 例程 做一个大总结 -
Linux中的pipe与named pipe(FIFO),即管道和命名管道
2021-05-13 03:41:28实际上这算不上什么限制,因为读和写操作是在不同的线程中实现的。Linux 还支持命名管道。对这些数字的早期评论员建议我,为公平起见,应该比较 Linux 的命名管道和 Windows 的命名管道。我写了另一个在 Linux 上使... -
Linux网络编程 - 在服务器端运用进程间通信之管道(pipe)
2022-01-08 19:33:17本文主要讲解进程间通信之一的管道(匿名管道)方式,讨论Linux系统中管道的工作原理及其使用方法,并将管道机制运用在Linux网络编程之中。 -
Arch Manjaro Linux Pacman 和 Aur 配置多线程下载
2018-10-06 01:38:34Arch Linux Pacman 和yaourt配置多线程下载0x01 配置Pacman多线程下载0x02 配置Yaourt(其他aur管理工具还没测试) 0x01 配置Pacman多线程下载 sudo pacman -S axel sudo gedit /etc/pacman.conf 注销已有的... -
07LinuxC进程间通信之管道pipe多个写端或者多个读端,案例4(非常重要)
2021-01-10 12:29:27是否允许,一个pipe有一个写端,多个读端呢?是否允许有一个读端多个写端呢? 前面已经说了,是允许的。 #include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <string.h&... -
【Linux系统编程】Linux线程浅析
2019-11-08 18:09:04进程和线程区别02. LinuxThreads03. NPTL04. NGPT05. 附录 01. 进程和线程区别 在许多经典的操作系统教科书中,总是把进程定义为程序的执行实例,它并不执行什么, 只是维护应用程序所需的各种资源,而线程则是真正... -
Linux线程实现机制
2019-12-18 10:48:32一.基础知识:线程和进程 按照教科书上的定义,进程是资源管理的最小单位,线程是程序执行的最小单位。在操作系统设计上,从进程演化出线程,最主要的目的...一个进程当然可以拥有多个线程,此时,如果进程运行在S... -
linux C++ 多线程 堆栈
2013-07-22 13:49:13pthread的默认栈大小是1Mb 堆是和其他线程公用进程的堆 -
【Linux应用】Linux线程通信及锁机制同步
2021-06-16 15:19:43线程通信就是当多个线程共同操作共享的资源时,互相告知自己的状态以避免资源争夺。不同线程共享同一份全局内存区域,包括初始化数据段、未初始化数据段及堆内存段,故线程之间可方便快速地共享全局或堆数据。线程间...