嵌入式:IO Day8

文章提供了两个C语言程序,分别展示了如何使用消息队列进行结构体数据的传输以及如何利用三个信号灯集实现三个进程间的同步,输出序列ABCABCABC...。代码中包含了msgsnd和msgrcv函数用于消息队列的发送和接收,以及信号灯操作函数P和V,用于资源的申请和释放。
摘要由CSDN通过智能技术生成

 1.使用消息队列,完成对结构体数据的传输

 源码:

msgsnd.c

#include <myhead.h>

typedef struct{
	long msgtype;
	struct{
		char name[10];
		char age[5];
	};
}Msginfo;

#define MSGSZ (sizeof(Msginfo) - sizeof(long))

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

	//创建、定义消息队列
	int msgid;
	if((msgid = msgget(key, IPC_CREAT | 0664)) == -1){
		perror("msgget error");
		return -1;
	}

	//发送消息队列
	Msginfo msg = {.msgtype = 10};

	while(1){
		//输入正文内容
		printf("请输入姓名:\n");
		fgets(msg.name, sizeof(msg.name), stdin);
		msg.name[strlen(msg.name) - 1] = '\0';
		printf("请输入年龄:\n");
		fgets(msg.age, sizeof(msg.age), stdin);

		//发送
		if(msgsnd(msgid, &msg, MSGSZ, 0) == -1){
			perror("msgsnd error");
			return -1;
		}

		if(strcmp(msg.name, "quit") == 0){
			break;
		}
	}

	//删除队列
	msgctl(msgid, IPC_RMID, NULL);
	return 0;
}

msgrcv.c

#include <myhead.h>

typedef struct{
	long msgtype;
	struct{
		char name[10];
		char age[5];
	};
}Msginfo;

#define MSGSZ (sizeof(Msginfo) - sizeof(long))

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

	//创建、定义消息队列
	int msgid;
	if((msgid = msgget(key, IPC_CREAT | 0664)) == -1){
		perror("msgget error");
		return -1;
	}

	//接收消息队列
	Msginfo msg = {.msgtype = 10};

	while(1){
		//接收
		if(msgrcv(msgid, &msg, MSGSZ, 0, 0) == -1){
			perror("msgrcv error");
			return -1;
		}

		printf("姓名:%s  年龄:%s\n", msg.name, msg.age);
		if(strcmp(msg.name, "quit") == 0){
			break;
		}
	}

	//删除队列
	msgctl(msgid, IPC_RMID, NULL);
	return 0;
}

2.使用三个信号灯集,完成三个进程间的同步,使用三个进程输出:ABCABCABC...

源码:

 sem.h

#ifndef __SEM_H__
#define __SEM_H__
 
int sem__init(); 	//创建一个信号灯集
int P(int semid, int semnum);  			//申请资源,将semnum资源减一
int V(int semid, int semnum); 			//释放资源,将semnum资源加一
int sem_del(int semid); 				//删除一个信号灯集
 
 
 
#endif /* SEM_H */

sem.c

#include <myhead.h>
 
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) */
};
 
//定义设置灯的值的函数
//给semid灯集的semno的这个灯值设置为value
void init_semnum_value(int semid, int semno, int value)
{
	union semun sem;
	sem.val = value;
 
	//设置信号灯的值
	semctl(semid, semno, SETVAL, sem);
}
 
int sem__init(int count) 	//创建一个信号灯集
{
	//1、申请key值
	key_t key;
	if ((key = ftok("/", 'm')) == -1)
	{
		perror("ftok");
		return -1;
	}
 
	//2、创建信号量
	int semid;
	if ((semid = semget(key, count, IPC_CREAT|IPC_EXCL|0664)) == -1)
	{
		if (errno == EEXIST)  	//说明信号灯集已经存在,直接打开即可
		{
			semid = semget(key, count, IPC_CREAT|0664);
		}
		else
		{
			perror("semget");	
			return -1;
		}
		
	}
	else
	{
		//原本不存在,重新创建一个需要对其初始化
		init_semnum_value(semid, 0, 0); 		//0号灯value初始化为0
		init_semnum_value(semid, 1, 0); 		//1号灯value初始化为0
		init_semnum_value(semid, 2, 1); 		//2号灯value初始化为1
	}
 
	return semid;   		//将申请的信号灯集id返回
 
}
 
int P(int semid, int semnum)  			//申请资源,将semnum资源减一
{
	struct sembuf buf; 			//定义有关灯操作的结构体
	buf.sem_num = semnum; 		//表明要更改的灯的编号
	buf.sem_op = -1; 		//表明要申请资源
	buf.sem_flg = 0; 		//阻塞等待
	
	//调用op函数
	semop(semid, &buf, 1);
	return 0;
}
int V(int semid, int semnum) 			//释放资源,将semnum资源加一
{
	struct sembuf buf; 			//定义有关灯操作的结构体
	buf.sem_num = semnum; 		//表示要更改的灯的编号
	buf.sem_op = 1; 		//表明要释放资源
	buf.sem_flg = 0; 		//阻塞等待
	
	//调用op函数
	semop(semid, &buf, 1);
	return 0;
 
}
int sem_del(int semid) 				//删除一个信号灯集
{
	//删除信号灯集
	return semctl(semid, 0, IPC_RMID, 0);
}

a.c

#include <myhead.h>
#include "sem.h"
 
#define SHMSZ 4096
#define COUNT 3
 
int main(int argc, const char *argv[])
{
	//1、定义一个信号量id
	int semid = sem__init(COUNT);
	//定义key值
	key_t key;
	if ((key = ftok("/", 'm')) == -1)
	{
		perror("ftok");
		return -1;
	}
 
	//定义共享内存id
	int shmid;
	//创建共享内存
	if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
	{
		perror("shmget");
		return -1;
	}
 
	//将创建好的共享内存映射到该程序中
	char *shmaddr;
	shmaddr = shmat(shmid, NULL, 0);
 
 
	while (1)
	{
		//2、申请2号灯的资源
		P(semid, 2);
 
		//向共享内存中读取数据
		shmaddr[0] = 'A';
 
		//3、释放0号灯的资源
		V(semid, 0);
	}
 
 
	//取消映射
	shmdt(shmaddr);
 
 
 
	return 0;
}

b.c

#include <myhead.h>
#include "sem.h"
 
#define SHMSZ 4096
 
int main(int argc, const char *argv[])
{
	//1、定义一个信号量id
	int semid = sem__init();
	//定义key值
	key_t key;
	if ((key = ftok("/", 'm')) == -1)
	{
		perror("ftok");
		return -1;
	}
 
	//定义共享内存id
	int shmid;
	//创建共享内存
	if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
	{
		perror("shmget");
		return -1;
	}
 
	//将创建好的共享内存映射到该程序中
	char *shmaddr;
	shmaddr = shmat(shmid, NULL, 0);
 
 
	//打印地址
	/*printf("shmaddr = %d\n", *shmaddr);*/
 
	while (1)
	{
		//2、申请0号灯的资源
		P(semid, 0);
 
		//向共享内存中读取数据
	
		shmaddr[1] = 'B';
 
		//3、释放1号灯的资源
		V(semid, 1);
	}
 
	//取消映射
	shmdt(shmaddr);
 
	//删除共享内容
	shmctl(shmid, IPC_RMID, NULL);
 
	//4、删除信号灯集
	sem_del(semid);
 
	return 0;
}

c.c

#include <myhead.h>
#include "sem.h"
 
#define SHMSZ 4096
#define COUNT 3
 
int main(int argc, const char *argv[])
{
	//1、定义一个信号量id
	int semid = sem__init(COUNT);
	//定义key值
	key_t key;
	if ((key = ftok("/", 'm')) == -1)
	{
		perror("ftok");
		return -1;
	}
 
	//定义共享内存id
	int shmid;
	//创建共享内存
	if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0664)) == -1)
	{
		perror("shmget");
		return -1;
	}
 
	//将创建好的共享内存映射到该程序中
	char *shmaddr;
	shmaddr = shmat(shmid, NULL, 0);
 
	while (1)
	{
		sleep(1);
		//2、申请1号灯的资源
		P(semid, 1);
		shmaddr[2] = 'C';
		shmaddr[3] = '\0';
		int i = 0;
		while (shmaddr[i] != '\0')
		{
			printf("%c", shmaddr[i++]);
			fflush(stdout);
			sleep(1);
		}
		//3、释放2号灯的资源
		V(semid, 2);
 
	}
 
 
	//取消映射
	shmdt(shmaddr);
 
 
 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值