ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

进程间通信

2021-06-09 22:57:53  阅读:187  来源: 互联网

标签:共享内存 int some 间通信 shmid 进程 include


1.信号

信号是比较复杂的通信方式,用于通知接收进程有某种事情发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信息语义函数signal外,还支持语义符合Posix 1标准的信号函数sigaction。

  • signal() 告诉系统内核怎么处理该信号
  • sigaction() 也是处理信号,但比signal更健壮
  • kill() 发送信号
  • alarm() 经过预定时间后发送SIGALARM信号

2.mmap文件映射:

也是一种共享内存,但是它是直接映射到磁盘中具体的文件,会涉及到磁盘的读写和io占用,不如shm共享内存效率高,但因为它的实际存储并没有反映到内存上,可以申请比较大的存储空间。

3.管道及有名管道

管道可用于具有亲缘关系进程间的通信,例如父子进程,但是有名管道允许无关系的进程间通信。管道其实就是建立一个FIFO文件,一个进程往里面写数据,另外的进程读取数据。
demo如下:

	#include <stdio.h>
	#include <unistd.h>
	#include <string.h>
	#include <sys/wait.h>
	#include <stdlib.h>

	void sys_err(const char *str)
	{
		perror(str);
		exit(1);
	}

	int main()
	{
		pid_t pid;
		char buf[1024];
		int fd[2];
		char *p = "test for pipe\n";
		if (pipe(fd) == -1)
			sys_err("pipe");

		pid = fork();
		if (pid < 0) 
		{
			sys_err("fork err");
		}
		else if(pid == 0)
		{
			//父进程   
			close(fd[1]);
			int len = read(fd[0], buf, sizeof(buf));
			write(STDOUT_FILENO, buf, len);  //输出到屏幕
			close(fd[0]);
		}
		else
		{
			//子进程
			close(fd[0]);
			write(fd[1], p, strlen(p)); //写入test for pipe
			wait(NULL);
			close(fd[1]);
		}

		return 0;
	}

4.消息队列

消息队列也叫报文队列,消息队列是消息的链接表,包括Posix消息队列和SystemV消息队列,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的信息,消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
发送消息demo如下:

	#include <stdlib.h>
	#include <stdio.h>
	#include <string.h>
	#include <errno.h>
	#include <unistd.h>
	#include <sys/types.h>
	#include <sys/ipc.h>
	#include <sys/msg.h>

	struct my_msg_st
	{
		long int my_msg_type;
		char some_text[BUFSIZ];
	};

	int main(void)
	{
		int running = 1;
		struct my_msg_st some_data;
		int msgid = 0;
		char buffer[BUFSIZ] = {0};
		memset((void*)&some_data, 0, sizeof(some_data));

		/*创建消息队列*/
		msgid=msgget((key_t)1234,0666 | IPC_CREAT);
		if(msgid==-1)
		{
			fprintf(stderr,"msgget failed with error:%d\n",errno);
			exit(EXIT_FAILURE);
		}

		/*循环向消息队列中添加消息*/
		while(running)
		{
			memset(buffer, 0, sizeof(buffer));
			printf("Enter some text:");
			fgets(buffer,BUFSIZ,stdin);
			some_data.my_msg_type=1;
			strcpy(some_data.some_text,buffer);

			/*添加消息*/
			if(msgsnd(msgid,(void *)&some_data,BUFSIZ,0)==-1)
			{
				fprintf(stderr,"msgsed failed\n");
				exit(EXIT_FAILURE);
			}

			/*用户输入的为“end”时结束循环*/
			if(strncmp(buffer,"end",3)==0)
			{
				running=0;
			}
		}
		exit(EXIT_SUCCESS);
	}

接收消息demo如下:

	#include <stdlib.h>
	#include <stdio.h>
	#include <string.h>
	#include <errno.h>
	#include <unistd.h>
	#include <sys/types.h>
	#include <sys/ipc.h>
	#include <sys/msg.h>

	struct my_msg_st
	{
		long int my_msg_type;
		char some_text[BUFSIZ];
	};

	int main(void)
	{
		int running=1;
		int msgid = 0;
		struct my_msg_st some_data;
		long int msg_to_receive=0;
		memset((void*)&some_data, 0, sizeof(some_data));

		/*创建消息队列*/
		msgid=msgget((key_t)1234,0666 | IPC_CREAT);
		if(msgid==-1)
		{
			fprintf(stderr,"msgget failed with error: %d\n",errno);
			exit(EXIT_FAILURE);
		}
		
		/*循环从消息队列中接收消息*/
		while(running)
		{
			/*读取消息*/
			if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1)
			{
				fprintf(stderr,"msgrcv failed with error: %d\n",errno);
				exit(EXIT_FAILURE);
			}

			printf("接收到的消息为: %s",some_data.some_text);

			/*接收到的消息为“end”时结束循环*/
			if(strncmp(some_data.some_text,"end",3) == 0)
			{
				running=0;
			}
		}

		/*从系统内核中移走消息队列*/
		if(msgctl(msgid,IPC_RMID,0) == -1)
		{
			fprintf(stderr,"msgctl(IPC_RMID) failed\n");
			exit(EXIT_FAILURE);
		}
		exit(EXIT_SUCCESS);
	}

5.共享内存

共享内存是一种文件映射,使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其他通信机制,如信号量结合使用,来达到进程间的同步及互斥。
demo如下:
写入共享内存:

	#include<stdlib.h>
	#include <sys/ipc.h>
	#include <sys/shm.h>
	#include<string.h>
	#include<errno.h>

	typedef struct _Teacher
	{
		char name[64];
		int age;
	}Teacher;

	int main(int argc, char *argv[])
	{
		int ret = 0;
		int    shmid = 0;
		//创建共享内存 ,相当于打开文件,文件不存在则创建
		shmid = shmget(0x2234, sizeof(Teacher), IPC_CREAT | 0666); 
		if (shmid == -1)
		{
			perror("shmget err");
			return errno;
		}
		printf("shmid:%d \n", shmid);
		Teacher *p = NULL;
		//将共享内存段连接到进程地址空间
		p = (Teacher*)shmat(shmid, NULL, 0);//第二个参数shmaddr为NULL,核心自动选择一个地址
		if (p == (void *)-1 )
		{
			perror("shmget err");
			return errno;
		}
		strcpy(p->name, "aaaa");
		p->age = 33;
		//将共享内存段与当前进程脱离
		shmdt(p);
			
		printf("键入1 删除共享内存,其他不删除\n");
		
		int num = 0;
		scanf("%d", &num);
		if (num == 1)
		{
			//用于控制共享内存
			ret = shmctl(shmid, IPC_RMID, NULL);//IPC_RMID为删除内存段
			if (ret < 0)
			{
				perror("rmerrr\n");
			}
		}                 

		return 0;    
	}

从共享内存读取:

	#include<stdio.h>
	#include <unistd.h>
	#include<stdlib.h>
	#include <sys/ipc.h>
	#include <sys/shm.h>
	#include<string.h>
	#include<errno.h>

	typedef struct _Teacher
	{
		char name[64];
		int age;
	}Teacher;

	int main(int argc, char *argv[])
	{
		int ret = 0;
		int    shmid = 0;
		//打开获取共享内存
		shmid = shmget(0x2234, 0, 0); 
		if (shmid == -1)
		{
			perror("shmget err");
			return errno;
		}
		printf("shmid:%d \n", shmid);
		Teacher *p = NULL;
		//将共享内存段连接到进程地址空间
		p = (Teacher*)shmat(shmid, NULL, 0);
		if (p == (void *)-1 )
		{
			perror("shmget err");
			return errno;
		}
		
		printf("name:%s\n", p->name);
		printf("age:%d \n", p->age);
		//将共享内存段与当前进程脱离
		shmdt(p);
		
		printf("键入1 程序暂停,其他退出\n");
		
		while(1)
		{
			sleep(1);
		}       
		return 0;
	}

6.socket

socket也就是套接字,最普遍的进程间通信机制,可用于不同机器之间的进程间通信,具体见网络编程。

 

标签:共享内存,int,some,间通信,shmid,进程,include
来源: https://blog.51cto.com/u_14438799/2887126

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有