嵌入式学习-IO进程线程-Day7

本文详细介绍了如何使用C语言通过消息队列实现两个进程之间的通信,以及如何用信号通信进行进程间的控制,还展示了如何使用共享内存进行进程间数据交换。
摘要由CSDN通过智能技术生成

Day7

思维导图

在这里插入图片描述

作业

1、使用消息队列完成两个进程之间相互通信

代码

send.c

#include<myhead.h>

//定义消息结构体类型
struct msgbuf
{
	long mtype;         //消息类型
	char mtext[64];       //消息正文
};

//定义一个宏,表示正文大小
#define SIZE (sizeof(struct msgbuf) - sizeof(long))


int main(int argc, const char *argv[])
{
	//1、创建key值
	key_t key = 0;
	if((key = ftok("/", 't')) == -1)
	{
		perror("fork error");
		return -1;
	}

	printf("key = %#x\n", key);

	//2、使用key值创建一个消息队列
	int msqid = 0;
	if((msqid=msgget(key, IPC_CREAT|0664)) == -1)
	{
		perror("msgget error");
		return -1;
	}

	printf("msqid = %d\n", msqid);

	//此时就已经在内核空间创建出消息队列了

	struct msgbuf buf;

	pid_t pid=-1;
	pid = fork();

	if(pid>0)
	{
		//父进程

		//定义一个消息类型的容器

		//3、循环向消息队列中存放数据
		while(1)
		{		
			buf.mtype=2;
			printf("请输入要存放的数据:");
			fflush(stdout);
			
			fgets(buf.mtext,64,stdin);

			//将消息存放到消息队列中
			msgsnd(msqid, &buf, SIZE, 0);

			printf("发送成功\n");

			if(strcmp(buf.mtext, "quit") == 0)
			{
				break;
			}
	
		}
		
		wait(NULL);
	}else if(pid==0)
	{

		//3、循环向消息队列中读取数据
		while(1)
		{
			//从消息队列中读取消息
			msgrcv(msqid, &buf, SIZE, 1, 0);
			//第二个0表示阻塞形式接收消息

			printf("收到消息为:%s\n", buf.mtext);

			if(strcmp(buf.mtext, "quit") == 0)
			{
				break;
			}
		}

		//4、删除消息队列
		if(msgctl(msqid, IPC_RMID, NULL) == -1)
		{
			perror("msgctl error");
			return -1;
		}

		exit(EXIT_SUCCESS);
	}
	else
	{
		perror("fork error");
		return -1;
	}


	return 0;
}

receive.c

#include<myhead.h>

//定义消息结构体类型
struct msgbuf
{
	long mtype;         //消息类型
	char mtext[64];       //消息正文

};

//定义一个宏,表示正文大小
#define SIZE (sizeof(struct msgbuf) - sizeof(long))


int main(int argc, const char *argv[])
{
	//1、创建key值
	key_t key = 0;
	if((key = ftok("/", 't')) == -1)
	{
		perror("fork error");
		return -1;
	}

	printf("key = %#x\n", key);

	//2、使用key值创建一个消息队列
	int msqid = 0;
	if((msqid=msgget(key, IPC_CREAT|0664)) == -1)
	{
		perror("msgget error");
		return -1;
	}

	printf("msqid = %d\n", msqid);

	//此时就已经在内核空间创建出消息队列了
	struct msgbuf buf;

	pid_t pid=-1;
	pid = fork();

	if(pid>0)
	{
		//父进程

		//3、循环向消息队列中存放数据
		while(1)
		{		
			buf.mtype=1;
			printf("请输入要存放的数据:");
			fflush(stdout);

			fgets(buf.mtext,64,stdin);


			//将消息存放到消息队列中
			msgsnd(msqid, &buf, SIZE, 0);

			printf("发送成功\n");

			if(strcmp(buf.mtext, "quit") == 0)
			{
				break;
			}

	
		}



		wait(NULL);

	}else if(pid == 0)
	{
			//子进程

			//3、循环向消息队列中读取数据
			while(1)
			{
				//从消息队列中读取消息
				msgrcv(msqid, &buf, SIZE, 2, 0);
				//第二个0表示阻塞形式接收消息

				printf("收到消息为:%s\n", buf.mtext);

				if(strcmp(buf.mtext, "quit") == 0)
				{
					break;
				}
			}

			//4、删除消息队列
			if(msgctl(msqid, IPC_RMID, NULL) == -1)
			{
				perror("msgctl error");
				return -1;
			}

			exit(EXIT_SUCCESS);
	}else
	{
		perror("fork error");
		return -1;
	}


	return 0;
}
运行结果

在这里插入图片描述

2、将信号通信相关代码重新实现一遍

代码

signal

#include <myhead.h>
void handler(int signum)
{
	if(signum==SIGINT)
	{
		printf("用户按下ctrl+c键\n");
	}
	if(signum==SIGTSTP)
	{
		printf("用户按下ctrl+z键\n");
	}
	if(signum==SIGSTOP)
	{
		printf("用户按下ctrl+z键\n");
	}
}

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

/*	if(signal(SIGINT,SIG_IGN)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
*/	
	if(signal(SIGINT,SIG_DFL)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
/*
	if(signal(SIGINT,handler)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
*/
	while(1)
	{
		sleep(1);
		printf("哈哈哈哈\n");
	}
	return 0;
}

信号发送函数

#include<myhead.h>

//定义信号处理函数
void handler(int signo)
{
    if(signo == SIGUSR1)
    {
        printf("???\n");

        raise(SIGKILL);     //自杀
    }
}


int main(int argc, const char *argv[])
{
    
    //定义进程号
    pid_t pid = fork();

    if(pid > 0)
    {
        //父进程

        //将SIGUSR1信号绑定
        if(signal(SIGUSR1, handler) == SIG_ERR)
        {
            perror("signal error");
            return -1;
        }
        
        while(1)
        {
            printf("nonono\n");
            sleep(1);
        }

    }else if(pid == 0)
    {
        //子进程
        printf("die\n");

        sleep(3);

        printf("die with me \n");

        //向父进程发送一个信号
        kill(getppid(), SIGUSR1);

        exit(EXIT_SUCCESS);        //退出进程


    }else
    {
        perror("fork error");
        return -1;
    }


    return 0;
}

在这里插入图片描述

3、将共享内存相关代码重新实现一遍

代码

send.c

#include<myhead.h>
#define PAGE_SIZE 4096

int main(int argc, const char *argv[])
{
    //创建key值
    key_t key = -1;
    if((key = ftok("/", 't')) == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //将物理内存创建出共享内存段
    int shmid = 0;
    if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //将共享内存段地址映射到用户空间
    //NULL表示让系统自动选择页的分段
    //0表示当前进程对共享内存具有读写功能
    char *addr = (char *)shmat(shmid, NULL, 0);
    if(addr == (void *)-1)
    {
        perror("shmat error");
        return -1;
    }
    printf("addr = %p\n", addr);
    
    //操作共享内存
    //char buf[128] = "";
    while(1)
    {
        fgets(addr, PAGE_SIZE, stdin);   //从终端输入数据
        addr[strlen(addr) - 1] = '\0';    //将换行换成'\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;
    }

    while(1);

    return 0;
}


rece.c

#include<myhead.h>
#define PAGE_SIZE 4096

int main(int argc, const char *argv[])
{
    //创建key值
    key_t key = -1;
    if((key = ftok("/", 't')) == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //将物理内存创建出共享内存段
    int shmid = 0;
    if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //将共享内存段地址映射到用户空间
    //NULL表示让系统自动选择页的分段
    //0表示当前进程对共享内存具有读写功能
    char *addr = (char *)shmat(shmid, NULL, 0);
    if(addr == (void *)-1)
    {
        perror("shmat error");
        return -1;
    }
    printf("addr = %p\n", addr);
    
    //操作共享内存
    //char buf[128] = "";
    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、付费专栏及课程。

余额充值