11.12

有道云笔记

#ifndef __MYSEM_H__
#define __MYSEM_H__

//信号灯集的申请,初始化信号灯,并返回信号灯集的id
int create_sem(int semcount);

//申请信号灯资源操作 p操作
int P(int semid, int semno);

//释放信号灯资源操作 v操作
int V(int semid, int semno);

//信号灯集的删除
int del_sem(int semid);

#endif

#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) */
};

//初始化函数
int init_sem(int semid, int semno){
	int val = -1;
	printf("请输入编号为%d的灯的初始值:", semno);
	scanf("%d", &val);
	while(getchar() != '\n');

	//对当前灯进行赋初始化值
	//定义一个共用体变量
	union semun us;
	us.val = val;
	if(semctl(semid, semno, SETVAL, us) == -1){
		perror("set val error");
		return -1;
	}
	return 0;
}

//信号灯集的申请,初始化信号灯,并返回信号灯集的id
int create_sem(int semcount){
	//1、创建key值
	key_t key = ftok("/", 'y');
	if(key == -1){
		perror("ftok error");
		return -1;
	}

	//2、通过key值创建一个信号灯集
	int semid = semget(key, semcount, IPC_CREAT | IPC_EXCL | 0664);
	if(semid == -1){
		if(errno == EEXIST){
			//说明信号灯集已经存在,无需创建直接打开即可
			semid = semget(key, semcount, IPC_CREAT);
			return semid; //之后的进程打开该信号灯集只需要返回该信号灯集ID即可
		}
		perror("semget error");
		return -1;
	}

	//3、给信号灯集中的信号灯进行初始化操作
	for(int i=0; i<semcount; i++){
		init_sem(semid, i); //初始化编号为i的灯value值
	}

	//4、返回值为信号灯集的id
	return semid;
}

//申请信号灯资源操作 p操作
int P(int semid, int semno){
	//定义一个操作的结构体变量
	struct sembuf buf;
	buf.sem_num = semno; //要操作的灯的编号
	buf.sem_op = -1; //表示申请资源操作
	buf.sem_flg = 0; //如果没有资源,则阻塞等待

	//调用semop函数完成p操作
	if(semop(semid, &buf, 1) == -1){
		perror("P error");
		return -1;
	}
	return 0;
}

//释放信号灯资源操作 v操作
int V(int semid, int semno){
	//定义一个操作的结构体变量
	struct sembuf buf;
	buf.sem_num = semno; //要操作的灯的编号
	buf.sem_op = 1; //表示释放资源操作
	buf.sem_flg = 0; //如果没有资源,则阻塞等待

	//调用semop函数完成V操作
	if(semop(semid, &buf, 1) == -1){
		perror("V error");
		return -1;
	}
	return 0;
}

//信号灯集的删除
int del_sem(int semid){
	//调用semc函数完成信号灯集的删除
	if(semctl(semid, 0, IPC_RMID, 0) == -1){
		perror("semctl error");
		return -1;
	}
	return 0;
}
#include <myhead.h>

#define PAGE_SIZE 4096

/*
 * function:    使用共享内存和信号量, 循环打印ABC
 * @param [ in]
 * p:申请资源的信号灯的编号,v:释放资源的信号灯的编号,c:打印的字符,semid:共享内存段id
 * @param [out] 
 * @return      
 */
int task(int p, int v, char c, int semid){

	//创建一个key值
	key_t key = ftok("/", 't');
	if(key == -1){
		perror("ftok error");
		return -1;
	}

	//通过key值创建共享内存段
	int shmid = shmget(key, PAGE_SIZE, IPC_CREAT | 0664);
	if(shmid == -1){
		perror("shmget error");
		return -1;
	}

	//将共享内存段映射到用户空间
	char *addr = (char *)shmat(shmid, NULL, 0);
	if(addr == (void *)-1){
		perror("shmat error");
		return -1;
	}

	//使用共享内存段,每个字符只打印5次
	int i = 5;
	while(i > 0){

		//P操作
		P(semid, p);
		
		//写入字符并打印
		*addr = c;
		printf("%c", *addr);
		fflush(stdout);
		
		sleep(1);

		//V操作
		V(semid, v);

		i--;

	}

	//取消映射
	if(shmdt(addr) == -1){
		perror("shmdt error");
		return -1;
	}

	return 0;

}

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

	//创建信号灯集,获取信号灯集ID
	int semid = create_sem(3);

	//开启第一个子进程
	int pid1 = fork();
	if(pid1 > 0){
		
		//开启第二个子进程
		int pid2 = fork();

		if(pid2 > 0){
			
			//主进程
			task(2, 0, 'A', semid);
		
		}else if(pid2 == 0){
			
			//第二个子进程
			task(0, 1, 'B', semid);
			exit(EXIT_SUCCESS);

		}else{

			perror("fork error");
			return -1;

		}

	}else if(pid1 == 0){
		
		//第一个子进程
		task(1, 2, 'C', semid);
		exit(EXIT_SUCCESS);

	}else{

		perror("fork error");
		return -1;

	}

	//回收子进程资源
	wait(NULL);
	wait(NULL);

	//在最后打印换行
	putchar(10);

	//删除信号灯集
	del_sem(semid);

	return 0;
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值