【linux草鞋应用编程系列】_3_ 进程间通信
一、进程间通信
PIPE(2) Linux Programmer’s Manual PIPE(2) NAMEpipe - create pipe SYNOPSIS#include <unistd.h>int pipe(int filedes[2]); //参数为一个长度为2 的整型数组的数组首地址, 为输出参数,
#include <stdio.h> #include <unistd.h> #include <stdlib.h>int main(int argc,char* argv[]) {int fd_pipe[2];pid_t pid;char buf[32];//创建管道if( pipe(fd_pipe) ){perror("create pipe");exit(1);}pid=fork();if( 0==pid ){/*close(fd_pipe[1]); //关闭写端*/read(fd_pipe[0], buf,sizeof(buf));printf("in child process read data from pipe.\n");printf("the data read from pipe is:%s\n",buf);exit(0);}/*close(fd_pipe[0]); //关闭读端*/write(fd_pipe[1], "pipe test",sizeof("pipe test"));sleep(1);return 0; }
[root@localhost ipc]# gcc main.c [root@localhost ipc]# ./a.out in child process read data from pipe. the data read from pipe is:pipe test
#include <stdio.h> #include <unistd.h> #include <stdlib.h>#define CHAR "pipe test from child to parent\n"int main(int argc,char* argv[]) {int fd_pipe[2];pid_t pid;char buf[32];//创建管道if( pipe(fd_pipe) ){perror("create pipe");exit(1);}pid=fork();if( 0==pid ){close(fd_pipe[0]);write(fd_pipe[1],CHAR,sizeof(CHAR));exit(0);} close(fd_pipe[1]);read(fd_pipe[0],buf,sizeof(buf));printf("data from child is: %s",buf);return 0; }
[root@localhost ipc]# gcc main.c [root@localhost ipc]# ./a.out data from child is: pipe test from child to parent
MKFIFO(3) Linux Programmer’s Manual MKFIFO(3) NAMEmkfifo - make a FIFO special file (a named pipe) SYNOPSIS#include <sys/types.h>#include <sys/stat.h>int mkfifo( const char *pathname, //生成的管道特殊文件的位置和文件名mode_t mode); //管道特殊文件的访问权限
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h>#define CHAR "pipe named\n"int main(int argc,char* argv[]) {int fd;int ret;//创建管道ret=mkfifo("./fifo-pipe",0666);if(ret){perror("mkfifo: fifo-pipe");exit(0);}fd=open("./fifo-pipe",O_WRONLY);write(fd,CHAR,sizeof(CHAR));close(fd);return 0; }
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h>int main(int argc,char* argv[]) {int fd;int ret;char buf[32];//打开命名管道文件fd=open("./fifo-pipe",O_RDONLY);if(-1 == fd){perror("open fifo-pipe");exit(1);}ret=read(fd,buf,sizeof(buf));if(ret<0){perror("read fifo-pipe");exit(1);}printf("the data read from fifo pipe:%s\n",buf);close(fd);return 0; }
[root@localhost pipe]# ll //查看没有 fifo-pipe 的命名管道文件 总计 28 -rw-r--r-- 1 root root 560 12-11 16:57 pipe_fork.c -rw-r--r-- 1 root root 500 12-11 17:15 pipe-r.c -rw-r--r-- 1 root root 405 12-11 17:17 pipe-w.c -rwxr-xr-x 1 root root 5359 12-11 17:15 rp -rwxr-xr-x 1 root root 5296 12-11 17:17 wp [root@localhost pipe]# ./wp & //wp运行,并且进入后台 [1] 29409 [root@localhost pipe]# jobs [1]+ Running ./wp & //wp在后台运行, 等待命名管道的数据被读取, 即wp 阻塞 [root@localhost pipe]# ./rp //rp 读取管道数据, the data read from fifo pipe:pipe named //数据读取成功 [1]+ Done ./wp //管道中的数据被读取完后,wp不再阻塞,返回 [root@localhost pipe]# jobs [root@localhost pipe]# ll 总计 28 prw-r--r-- 1 root root 0 12-11 17:23 fifo-pipe //生成一个命名管道文件 -rw-r--r-- 1 root root 560 12-11 16:57 pipe_fork.c -rw-r--r-- 1 root root 500 12-11 17:15 pipe-r.c -rw-r--r-- 1 root root 405 12-11 17:17 pipe-w.c -rwxr-xr-x 1 root root 5359 12-11 17:15 rp -rwxr-xr-x 1 root root 5296 12-11 17:17 wp [root@localhost pipe]#
FTOK(3) Linux Programmer’s Manual FTOK(3) NAMEftok - convert a pathname and a project identifier to a System V IPC key//由一个特定的工程号和文件生成一个特定的IPC键值, SYNOPSIS# include <sys/types.h># include <sys/ipc.h>key_t ftok(const char *pathname, //文件名int proj_id); //工程号
MSGGET(2) Linux Programmer’s Manual MSGGET(2) NAMEmsgget - get a message queue identifierSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget( key_t key, //IPC 键值int msgflg); //打开或者创建标志, 可以取值 IPC_CREAT
MSGOP(2) Linux Programmer’s Manual MSGOP(2) NAMEmsgop - message operations SYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgsnd(int msqid, //消息队列IDconst void *msgp, //要发送的消息的消息结构体size_t msgsz, //消息字符串的大小,或者消息结构的大小int msgflg); // 消息标志 ssize_t msgrcv(int msqid, //消息队列IDvoid *msgp, //接受消息的消息结构体指针size_t msgsz, //消息结构体的大小long msgtyp, //指定要接收到消息的类型int msgflg); //消息标志 要发送或接收消息,还需要定义一个如下格式的结构体:struct msgbuf {long mtype; /* message type, must be > 0 */ //消息类型, 这个值必须大于 0char mtext[1]; /* message data */ //要发送的消息数据, 字符数组长度可以根据实际需要定义 };
MSGCTL(2) Linux Programmer’s Manual MSGCTL(2) NAMEmsgctl - message control operations SYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgctl(int msqid, //消息队列IDint cmd, //操作命令, 操作命令有很多,删除消息队列用 IPC_RMID 命令struct msqid_ds *buf); //输出参数,通过这个结构体可获取消息队列的状态信息,如果不需要获取//消息队列的信息,那么就设置为NULL
#include <stdio.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdlib.h>typedef struct {long type;char data[128]; }msgbuf;int main(void) {int ret;key_t key;int msgid;msgbuf msg={type: 1,data: "this is a message queue test.\n",};//获取键值key=ftok("./msgsnd.c",1);if(-1 == key){perror("ftok");exit(1);}//打开或创建一个消息队列msgid=msgget(key,IPC_CREAT);if(-1 == msgid ){perror("msgget");exit(2);}//发送消息ret=msgsnd(msgid,&msg,sizeof(msgbuf),0);if(-1 == ret){perror("msgsnd");}return 0; }
#include <stdio.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdlib.h>typedef struct {long type;char data[128]; }msgbuf;int main(int argc,char* argv[]) {int ret;key_t key;int msgid;msgbuf msg;//获取键值key=ftok("./msgsnd.c",1);if(-1 == key ){perror("ftok");exit(1);}//打开消息队列msgid=msgget(key,0);if(-1 == msgid ){perror("msgget");exit(2);}//接收消息ret=msgrcv(msgid, &msg, sizeof(msgbuf),1,0);if(-1 == ret){perror("msgrcv");exit(3);}printf("the recive message is: %s",msg.data);//删除消息队列 msgctl(msgid,IPC_RMID,NULL);return 0; }
[root@localhost msg]# gcc msgsnd.c -o snd [root@localhost msg]# gcc msgrcv.c -o rcv [root@localhost msg]# ./snd [root@localhost msg]# ./rcv the recive message is: this is a message queue test. [root@localhost msg]#
/* semop system calls takes an array of these. */ struct sembuf {unsigned short sem_num; /* semaphore index in array */ //信号量集合中的信号量索引值,即表示信号量集合中第几个信号量short sem_op; /* semaphore operation */ //要对信号量进行的操作,=-1 表示信号量不可获取, =1 表示可以获取信号量short sem_flg; /* operation flags */ //信号量标志 };
SEMGET(2) Linux Programmer’s Manual SEMGET(2) NAMEsemget - get a semaphore set identifier //获取一个信号集合的ID SYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semget( key_t key, //IPC键值int nsems, //信号量集合中信号量的个数, 要创建的信号量到个数int semflg); //信号量的标志, 同OPEN的打开标志类似
SEMCTL(2) Linux Programmer’s Manual SEMCTL(2) NAMEsemctl - semaphore control operationsSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semctl(int semid, //信号量集合ID int semnum, //信号量集合中的信号量索引值int cmd, //要对信号量进行的操作,可以使用的命名: IPC_SET、IPC_STAT、IPC_INFO、GETVAL、SETVAL.........); //最后一个参数根据 操作的不同,可以传递,也可以不传递
union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO(Linux specific) */};
SEMOP(2) Linux Programmer’s Manual SEMOP(2)NAMEsemop, semtimedop - semaphore operationsSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semop(int semid, //信号量集合IDstruct sembuf *sops, //信号量结构体指针unsigned nsops); //表示要操作的信号量个数int semtimedop(int semid, //信号量集合IDstruct sembuf *sops, //信号量结构体指针unsigned nsops, //表示要操作的信号量个数struct timespec *timeout); //表示超时等待时间,如果在超时时间内没有获取到可操作的信号量,就返回
#include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h> #include <fcntl.h> #include <stdlib.h>int main(void) {int i;int j;int ret;int fd; pid_t pid;key_t key;int semid;char buf[64];int size;struct sembuf sembuf;/*sembuf=(struct sembuf*)malloc(sizeof (struct sembuf));*///打开文件,用来进行操作fd=open("./test",O_RDWR | O_CREAT | O_TRUNC,0666);if(-1 == fd){perror("open");exit(1);}//IPC键值key=ftok("./main.c",1);if(-1 == key){perror("ftok");exit(2);}//获取信号量集合的IDsemid=semget(key,1,IPC_CREAT);if(-1 == semid ){perror("semget");exit(3);}//初始化信号量集合中的第一个信号量,设定信号量的值为0 , sem.sem_op = 0;ret=semctl(semid, 0, SETVAL, 1);pid=fork();if( pid==0 ) //----------------子进程------------ {//信号量的P 操作, 即加锁信号量sembuf.sem_num=0;sembuf.sem_op=-1;sembuf.sem_flg=0;semop(semid,&sembuf,1);size=sprintf(buf,"pid=%d, ppid=%d\n",getpid(),getppid());for(i=0;i<5;i++){j=0;while(j<size){ret=write(fd,&buf[j++], 1);if(-1 == ret){perror("write");exit(4);}usleep(1);}}//信号量的V操作,即解锁信号量sembuf.sem_num=0;sembuf.sem_op=1;sembuf.sem_flg=0;semop(semid,&sembuf,1);exit(0);}//---------------子进程结束---------------------//-----------------------父进程---------------//信号量的P 操作, 即加锁信号量sembuf.sem_num=0;sembuf.sem_op=-1;sembuf.sem_flg=0;semop(semid,&sembuf,1);size=sprintf(buf,"pid=%d, ppid=%d\n",getpid(),getppid());for(i=0;i<5;i++){j=0;while(j<size){ret=write(fd,&buf[j++], 1);if(-1 == ret){perror("write");exit(4);}usleep(1);}}//信号量的V操作,即解锁信号量sembuf.sem_num=0;sembuf.sem_op=1;sembuf.sem_flg=0;semop(semid,&sembuf,1);semctl(semid,0,IPC_RMID);close(fd);return 0; }
pid=1114, ppid=714 pid=1114, ppid=714 pid=1114, ppid=714 pid=1114, ppid=714 pid=1114, ppid=714 pid=1115, ppid=1 pid=1115, ppid=1 pid=1115, ppid=1 pid=1115, ppid=1 pid=1115, ppid=1
#include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h> #include <fcntl.h> #include <stdlib.h>int main(void) {int i;int j;int ret;int fd; pid_t pid;key_t key;int semid;char buf[64];int size;struct sembuf sembuf;/*sembuf=(struct sembuf*)malloc(sizeof (struct sembuf));*///打开文件,用来进行操作fd=open("./test",O_RDWR | O_CREAT | O_TRUNC,0666);if(-1 == fd){perror("open");exit(1);}//IPC键值key=ftok("./main.c",1);if(-1 == key){perror("ftok");exit(2);}//获取信号量集合的IDsemid=semget(key,1,IPC_CREAT);if(-1 == semid ){perror("semget");exit(3);}//初始化信号量集合中的第一个信号量,设定信号量的值为0 ret=semctl(semid, 0, SETVAL, 1);pid=fork();if( pid==0 ) //----------------子进程------------ {//信号量的P 操作, 即加锁信号量sembuf.sem_num=0;sembuf.sem_op=-1;sembuf.sem_flg=0;/*semop(semid,&sembuf,1);*/ //取消信号量到作用 size=sprintf(buf,"pid=%d, ppid=%d\n",getpid(),getppid());for(i=0;i<5;i++){j=0;while(j<size){ret=write(fd,&buf[j++], 1);if(-1 == ret){perror("write");exit(4);}usleep(1);}}//信号量的V操作,即解锁信号量sembuf.sem_num=0;sembuf.sem_op=1;sembuf.sem_flg=0;/*semop(semid,&sembuf,1);*/ //取消信号量到作用 exit(0);}//---------------子进程结束---------------------//-----------------------父进程---------------//信号量的P 操作, 即加锁信号量sembuf.sem_num=0;sembuf.sem_op=-1;sembuf.sem_flg=0;/*semop(semid,&sembuf,1);*/ //取消信号量到作用 size=sprintf(buf,"pid=%d, ppid=%d\n",getpid(),getppid());for(i=0;i<5;i++){j=0;while(j<size){ret=write(fd,&buf[j++], 1);if(-1 == ret){perror("write");exit(4);}usleep(1);}}//信号量的V操作,即解锁信号量sembuf.sem_num=0;sembuf.sem_op=1;sembuf.sem_flg=0;/*semop(semid,&sembuf,1);*/ //取消信号量到作用 semctl(semid,0,IPC_RMID);close(fd);return 0; }
ppiidd==22333387,, ppppiidd==2731347ppiidd==22333378,, ppppiidd==721343 7p ipdi=d2=323373,8 ,p ppipdi=d7=1243 3p7i dp=i2d3=3273,3 8p,p ipdp=i7d1=42 3p3i7d =p2i3d3=72,3 3p8p,i dp=p7i1d4= 2337
SHMGET(2) Linux Programmer’s Manual SHMGET(2) NAMEshmget - allocates a shared memory segment SYNOPSIS#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, //IPC 键值size_t size, //要申请的内存空间的大小int shmflg); //共享内存的空间打开标志 ,与 open 的打开标志类似, 返回值:申请成功返回共享内存标识ID, 失败返回-1。
SHMOP(2) Linux Programmer’s Manual SHMOP(2) NAMEshmop - shared memory operations SYNOPSIS#include <sys/types.h>#include <sys/shm.h>void *shmat(int shmid, //共享内存标志IDconst void *shmaddr, //传递NULL,表示要系统分配存储缓冲区,传递地址表示指定地址int shmflg); //打开标志,int shmdt(const void *shmaddr); //删除共享内存
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <string.h>#define SHM_SIZE 128int main(int argc,char* argv[]) {key_t key;int shm_id;char* shm_p;//获取IPC 键值key=ftok("./shm-w.c",1);if(-1 == key){perror("ftok");exit(1);}//申请共享内存空间,大小为 SHM_SIZEshm_id=shmget(key,SHM_SIZE,IPC_CREAT);if(-1 == shm_id ){perror("shmget");exit(2);}//将申请的共享内存映射到用户空间shm_p=shmat(shm_id,NULL,0); // if(NULL == shm_p ){perror("shmat");exit(3);}//将数据写入到共享内存 写入到数据可以在其他进程中读取memset(shm_p,0,SHM_SIZE);strcpy(shm_p, "this is a sheard memmory.\n"); //这个函数不安全,需要注意return 0; }从共享内存中读取数据的文件 shm-r.c #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <string.h>#define SHM_SIZE 128int main(int argc,char* argv[]) {key_t key;int shm_id;char* shm_p;char buf[SHM_SIZE];//获取IPC 键值key=ftok("./shm-w.c",1);if(-1 == key){perror("ftok");exit(1);}//申请共享内存空间,大小为 SHM_SIZEshm_id=shmget(key,SHM_SIZE,IPC_CREAT);if(-1 == shm_id ){perror("shmget");exit(2);}//将申请的共享内存映射到用户空间shm_p=shmat(shm_id,NULL,0); // if(NULL == shm_p ){perror("shmat");exit(3);}//从共享内存读取数据memset(buf,0,SHM_SIZE);strcpy(buf, shm_p); //这个函数不安全,需要注意printf("the data read from sheard memory is: %s",buf);shmdt(shm_p); //申请撤销共享内存return 0; }
[root@localhost shm]# gcc shm-w.c -o shmw [root@localhost shm]# gcc shm-r.c -o shmr [root@localhost shm]# ./shmw [root@localhost shm]# ./shmr the data read from sheard memory is: this is a sheard memmory. [root@localhost shm]#
【Linux草鞋应用编程系列】_3_进程间通信
本系列文章未完,待续。
如果查看的过程中发现错误,请不吝指教,包括错别字、标点符号等。
前篇:【linux草鞋应用编程系列】_2_ 环境变量和进程控制
转载于:https://www.cnblogs.com/volcanol/p/3473642.html
【linux草鞋应用编程系列】_3_ 进程间通信相关推荐
- 【linux草鞋应用编程系列】_4_ 应用程序多线程
一.应用程序多线程 当一个计算机上具有多个CPU核心的时候,每个CPU核心都可以执行代码,此时如果使用单线程,那么这个线程只能在一个 CPU上运行,那么其他的CPU核心就处于空闲状态,浪费了系统资源: ...
- 【linux草鞋应用编程系列】_2_ 环境变量和进程控制
一. 环境变量 应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作. 在linux中有两种方法获取环境变量,分述如下. 1.通过main函数的参数获取环境变量 main函数的多种 ...
- Linux环境高级编程函数,Linux环境高级编程--出错处理(CLStatus)
很多程序库对外提供若干类,每个方法出错时如何告知调用者是否出错,以及出错码(在Linux上在error.h中的全局errno就是保存我们Linux程序执行的出错码的)?方法很多,为了简化起见,函数将返 ...
- Linux内核模块编程系列1-极简内核模块编写
1.准备工作 使用如下命令查看自己Linux的内核版本 uname -a 结果如下: Linux VM-73-203-debian 4.9.0-6-amd64 #1 SMP Debian 4.9.88 ...
- 视频教程-Kali Linux渗透测试全程课与脚本语言编程系列课程-渗透测试
Kali Linux渗透测试全程课与脚本语言编程系列课程 本人有多年的服务器高级运维与开发经验,擅长计算机与服务器攻防及网络攻防技术!对网络安全领域有持续的关注和研究! 林晓炜 ¥899.00 立即订 ...
- 嵌入式Linux 串口编程系列2--termios的VMIN和VTIME深入理解
在上一篇文章中,我们介绍了串口的一些基本知识.串口配置接口 termios结构体的概念,串口的配置参数有n多个,这里面不用都背下来,什么时候使用,翻看手册即可,但是有两个 参数是一定要理解的,就是VM ...
- 嵌入式Linux 串口编程系列3——通过VTIM、VMIN、select实现串口不定长数据接收功能
上一篇文章中,我们详细分析了VTIM和VMIN的功能, <嵌入式Linux 串口编程系列2--termios的VMIN和VTIME深入理解> 也明白了这两个参数设计的初衷和使用方法,接下来 ...
- Linux下C编程实战
2019独角兽企业重金招聘Python工程师标准>>> Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于 ...
- Linux驱动视频教程推荐,隆重推荐:linux驱动基础开发系列免费教程独家版本
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 相信大家经常网上闲逛,会经常碰到很多的linux免费教程之类得,但是今天我推荐的这个linux驱动基础开发系列免费教程可不是网上可以随意找到得.废话少说: ...
最新文章
- SCOI2009 最长距离
- 转载 一个渣硕iOS春招总结 | 掘金技术征文
- uniapp处理IOS底部横条安全区域
- 【新产品发布】《EVC8021 RS-232RS-485/422 隔离接口转换器》
- golang数据类型与MySQL数据类型的对应
- springMVC上传下载
- MySQL:从B树到B+树到索引再到存储引擎
- http协议报文体_Java面试中可能涉及到的通信协议类问题
- 数据结构——双向链表的实现
- [洛谷P5048][Ynoi2019模拟赛]Yuno loves sqrt technology III
- nodejs 本地php服务器,node.js创建本地服务器详解
- 聚划算的夜场新生意 “三叉戟”打通夜间消费命脉
- log4j deadlock
- 我是如何在自学编程9个月后找到工作的
- 自己制作的4X4光立方焊接时候出现的问题
- filenet java配置_连接到filenet的外部java应用程序服务器
- GitLab 创建项目组及将代码导入项目
- RPG Maker MZ如何导入dlc素材?
- 直击|支付宝还信用卡下月开始收费 每月2000免费额度
- git 新建分支并切换到该分支_Git 从master拉取代码创建新分支 并且再将修改合并到master...