进程之间的通信

1.思维导图

2.面试题 

消息队列原理:

消息队列是在内核空间创建消息队列(msgget),进程通过特定的函数msgsnd向消息队列中存放消息,存放的形式是结构体类型的,进程通过特定的函数msgrcv从消息队列中获取消息,即消息队列中需被取走的消息从消息队列中进入进程,且消息队列中不存在该消息了。

共享内存:

是将物理内存映射到不同进程中,且在内核中形成共享内存段,不同进程直接对映射出来的共享内存进行操作,无需用户空间和内核空间切换。

3.使用消息队列完成两个进程之间的通信

 #include<head.h>
struct msgbuf
{
	long mtype;
	char mtext[1024];
};
#define M (sizeof(struct msgbuf)-sizeof(long))

void handle(int signum)
{
	if(signum==SIGCHLD)
	{
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}

int main(int argc, const char *argv[])
{
	//回收子进程
	if(signal(SIGCHLD,handle)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
	//创建一个无名管道
	int pipefd[2];
	if(pipe(pipefd)!=0)
	{
		perror("pipe error");
		return -1;
	}
	//定义key值
	key_t key;
	if((key=ftok("./",'a'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	//创建消息队列
	int mspid;
	if((mspid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget erroor");
		return -1;
	}
	//定义容器
	struct msgbuf buf;
	//判断是否要存入数据

	//创建子进程
	pid_t pid=fork();
	if(pid>0)
	{
		//父进程发送消息
		close(pipefd[0]);
		while(1)
		{ 
			char flag;
			printf("是否要存入数据y/n:");
			flag=fgetc(stdin);
			write(pipefd[1],&flag,1);

			
			if(flag=='y'||flag=='Y')
			{	
			printf("要存入的类型:");
			scanf("%ld",&buf.mtype);
			getchar();
			printf("要存入的数据:");
			fflush(stdout);
			fgets(buf.mtext,sizeof(buf.mtext),stdin);
			buf.mtext[strlen(buf.mtext)-1]='\0';
			msgsnd(mspid,&buf,M,0);  //存入消息
			printf("发送成功!\n");
			}
			else
			{
				sleep(1);
			}
			if(strcmp(buf.mtext,"quit")==0)
			{
				break;
			}
		}
		close(pipefd[1]);
	}else if(pid==0)
	{
		//子进程读取消息
		long ty;
		close(pipefd[1]);
		while(1)
		{	
			char flag;
			read(pipefd[0],&flag,1);
			if(flag=='n'||flag=='N')
			{
				printf("要读取的消息类型:");
				scanf("%ld",&ty);
				getchar();
				msgrcv(mspid,&buf,M,ty,0);
				printf("收到消息:%s \n",buf.mtext);
			}
			if(strcmp(buf.mtext,"quit")==0)
			{
				break;
			}
		}
		close(pipefd[0]);
		exit(EXIT_SUCCESS);

	}else
	{
		perror("fork error");
		return -1;
	}
	if(msgctl(mspid,IPC_RMID,NULL)==-1)
	{
		perror("msgctl error");
		return -1;
	}
	return 0;
}
 #include<head.h>
struct msgbuf
{
	long mtype;
	char mtext[1024];
};
#define M (sizeof(struct msgbuf)-sizeof(long))

void handle(int signum)
{
	if(signum==SIGCHLD)
	{
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}

int main(int argc, const char *argv[])
{
	//回收子进程
	if(signal(SIGCHLD,handle)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
	//创建一个无名管道
	int pipefd[2];
	if(pipe(pipefd)!=0)
	{
		perror("pipe error");
		return -1;
	}
	//定义key值
	key_t key;
	if((key=ftok("./",'a'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	//创建消息队列
	int mspid;
	if((mspid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget erroor");
		return -1;
	}
	//定义容器
	struct msgbuf buf;
	//判断是否要存入数据

	//创建子进程
	pid_t pid=fork();
	if(pid==0)
	{
		//子进程发送消息
		close(pipefd[0]);
		while(1)
		{ 
			char flag;
			printf("是否要存入数据y/n:");
			flag=fgetc(stdin);
			write(pipefd[1],&flag,1);

			
			if(flag=='y'||flag=='Y')
			{	
			printf("要存入的类型:");
			scanf("%ld",&buf.mtype);
			getchar();
			printf("要存入的数据:");
			fflush(stdout);
			fgets(buf.mtext,sizeof(buf.mtext),stdin);
			buf.mtext[strlen(buf.mtext)-1]='\0';
			msgsnd(mspid,&buf,M,0);  //存入消息
			printf("发送成功!\n");
			}else
			{
				sleep(1);
			}
			if(strcmp(buf.mtext,"quit")==0)
			{
				break;
			}
		}
		close(pipefd[1]);
		exit(EXIT_SUCCESS);
	}else if(pid>0)
	{
		//父进程读取消息
		long ty;
		close(pipefd[1]);
		while(1)
		{	
			char flag;
			read(pipefd[0],&flag,1);
			if(flag=='n'||flag=='N')
			{
				printf("要读取的消息类型:");
				scanf("%ld",&ty);
				getchar();
				msgrcv(mspid,&buf,M,ty,0);
				printf("收到消息:%s\n",buf.mtext);
			}
			if(strcmp(buf.mtext,"quit")==0)
			{
				break;
			}
		}
		close(pipefd[0]);

	}else
	{
		perror("fork error");
		return -1;
	}
	if(msgctl(mspid,IPC_RMID,NULL)==-1)
	{
		perror("msgctl error");
		return -1;
	}
	return 0;
}

 

4.信号通信相关代码 

#include<head.h>

//定义信号处理函数
void handler(int signum)
{
    if(signum == SIGINT)      //表明要处理2号信号
    {
        printf("用户按下了ctrl + c键\n");
    }

    if(signum == SIGTSTP)          //处理暂停信号
    {

        printf("用户按下了ctrl + z键\n");
    }
}

int main(int argc, const char *argv[])
{
    //将SIGINT信号捕获
    if(signal(SIGINT, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    //绑定SIGTSTP信号 ctrl + z
    if(signal(SIGTSTP, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }



    while(1)
    {
        sleep(1);
        printf("我真的还想再活五百年\n");
    }

    return 0;
}

 

 5.共享内存相关代码

 发送端

#include<head.h>
#define M 4096

int main(int argc, const char *argv[])
{
	//创建key值
	key_t key=ftok("./",'t');
	if(key==-1)
	{
		perror("ftok error");
		return -1;
	}
	//创建共享内存段
	int shmid=shmget(key,M,IPC_CREAT|0664);
	if(shmid==-1)
	{
		perror("shmget error");
		return -1;
	}
	//将共享内存段地址映射到用户空间
	char *addr=shmat(shmid,NULL,0);
	if(addr==(void *)-1)
	{
		perror("shmat error");
		return -1;
	}
	//操作共享内存
	while(1)
	{
		fgets(addr,M,stdin);
		addr[strlen(addr)-1]='\0';
		if(strcmp(addr,"quit")==0)
		{
			break;
		}
	}

	//取消共享内存
	if(shmdt(addr)==-1)
	{
		perror("shmdt error");
		return -1;
	}
	//删除共享内存段
	if(shmctl(shmid,IPC_RMID,NULL)==-1)
	{
		perror("shmctl error");
		return -1;
	}
	return 0;
}

接受端

#include<head.h>
#define M 4096

int main(int argc, const char *argv[])
{
	//创建key值
	key_t key=ftok("./",'t');
	if(key==-1)
	{
		perror("ftok error");
		return -1;
	}
	//创建共享内存段
	int shmid=shmget(key,M,IPC_CREAT|0664);
	if(shmid==-1)
	{
		perror("shmget error");
		return -1;
	}
	//将共享内存段地址映射到用户空间
	char *addr=shmat(shmid,NULL,0);
	if(addr==(void *)-1)
	{
		perror("shmat error");
		return -1;
	}
	//操作共享内存
	while(1)
	{
		printf("共享内存段内容:%s\n",addr)	;
		sleep(1);
		if(strcmp(addr,"quit")==0)
		{
			break;
		}
	}

	//取消共享内存
	if(shmdt(addr)==-1)
	{
		perror("shmdt error");
		return -1;
	}
	//删除共享内存段
	if(shmctl(shmid,IPC_RMID,NULL)==-1)
	{
		perror("shmctl error");
		return -1;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值