2023/12/12 work

1.  使用三个程序来完成输出 ABCABCABCABCABC

#include "sem.h"

int main(int argc, const char *argv[])
{
	//创建进程
	pid_t pid1,pid2;
	int semid;
	//子进程1
	int num = 10;
	if((pid1 = fork()) == 0){
	
		//创建信号灯集
		semid = create_sem(3);
		if(semid == -1){
			perror("create_sem1 error");
			return -1;
		}

		while(num--){
		
			p_handle(semid,0);
			printf("C");
			fflush(stdout);
			v_handle(semid,1);
			sleep(1);
		}

		//进程退出
		exit(EXIT_SUCCESS);

	}else if((pid2 = fork()) == 0){
		//创建信号灯集
		semid = create_sem(3);
		if(semid == -1){
			perror("create_sem2 error");
			return -1;
		}

		while(num--){
		
			p_handle(semid,1);
			printf("B");
			fflush(stdout);
			v_handle(semid,2);
			sleep(1);
		}
		
		exit(EXIT_SUCCESS);
	}else {
			//创建信号灯集
		semid = create_sem(3);
		if(semid == -1){
			perror("create_sem2 error");
			return -1;
		}

		while(num--){
		
			p_handle(semid,2);
			printf("A");
			fflush(stdout);
			v_handle(semid,0);
			sleep(1);
		}
	
	}
	puts("");
	//信号灯删除
	del_sem(semid);
	wait(NULL);
	wait(NULL);
	
	return 0;
}

2.  将共享内存和信号灯集完成两个进程间通信程序重新实现一下

#ifndef _SEM_H__
#define _SEM_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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) */
};

#define PAGE_SIZE 4096

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

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

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

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

#endif

#include "sem.h"

int init_sem(int semid,int semno){
	//输入灯的初始值
	int val =-1;
	printf("请输入标号%d灯的初始值",semno);
	scanf("%d",&val);
	//定义共用体并初始化
	union semun un;
	un.val = val;

	if(semctl(semid,semno,SETVAL,un) == -1){
		perror("semctl error");
		return -1;
	}
	//成功返回 0
	return 0;
}

//信号灯申请,初始化并返回信号灯集id
int create_sem(int semcount){
	//1. 创建Key
	key_t key = ftok("/",'d');
	if(key == -1){
		perror("sem 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;
		}

		perror("sem semget error");
		return -1;
	}
	//3. 信号灯初始化(循环初始化)
	for(int i=0; i<semcount;i++){
		init_sem(semid,i);
	}
	//4. 返回
	return semid;
}

//申请信号灯资源操作, p 操作
int p_handle(int semid,int semno){
	//定义结构体变量,并初始化
	struct sembuf buf;
	//操作几号灯
	buf.sem_num = semno;
	//申请资源
	buf.sem_op = -1;
	//没有资源阻塞
	buf.sem_flg =0;

	if(semop(semid,&buf,1) ==-1){
		perror("semop error");
		return -1;
	}
	return 0;
}

//释放信号灯资源操作 V
int v_handle(int semid,int semno){
	//定义结构体变量,并初始化
	struct sembuf buf;
	//操作几号灯
	buf.sem_num = semno;
	//释放资源
	buf.sem_op = 1;
	//没有资源阻塞
	buf.sem_flg =0;

	if(semop(semid,&buf,1) ==-1){
		perror("semop error");
		return -1;
	}
	return 0;
}

//信号灯删除
int del_sem(int semid){
	//删除
	if(semctl(semid,0,IPC_RMID,0) ==-1){
		perror("del_sem semctl error");
		return -1;
	}
	return 0;
}




#include "sem.h"


int main(int argc, const char *argv[])
{
	//a. 创建信号灯集
	int semid = create_sem(2);
	if(semid == -1){
		perror("create_sem error");
		return -1;
	}

	printf("semsnd semid %d\n",semid);

	//1.创建key
	key_t key = ftok("/",'k');
	if(key == -1){
		perror("ftok error");
		return -1;
	}

	printf("semsnd key %#x\n",key);
		
	//2.通过key 创建共享内存段
	int ipc = shmget(key,PAGE_SIZE,IPC_CREAT|0664);
	if(ipc == -1){
		perror("shmget error");
		return -1;
	}

	printf("semsnd ipc %d\n",ipc);

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

	printf("semsnd ------------------------\n");

	//4. 使用共享内存
	while(1){
		//循环往共享内存写入数据
		//b. P操作,等待 1号灯
		p_handle(semid,1);
		printf("请输入>>>");
		fgets(addr,PAGE_SIZE,stdin);
		addr[strlen(addr)-1] = 0;

		//c. V操作 释放 0 号灯
		v_handle(semid,0);
		if(strcmp(addr,"tuichu") == 0){
			break;
		}
	}
	//5. 取消映射
	if(shmdt(addr) == -1){
		perror("semsnd shmdt error");
		return -1;
	}

	return 0;
}


#include "sem.h"


int main(int argc, const char *argv[])
{
	int semid = create_sem(2);
	if(semid == -1){
		perror("semaccept semid error");
		return -1;
	}

	printf("semaccept semid %d\n",semid);

	//接收内存消息
	key_t key = ftok("/",'k');
	if(key == -1){
		perror("accept ftok error");
	}

	printf("semaccept key %#x\n",key);
	//2.通过key 创建共享内存段
	int ipc = shmget(key,PAGE_SIZE,IPC_CREAT|0664);
	if(ipc == -1){
		perror("shmget error");
		return -1;
	}

	printf("semaccept ipc %d\n",ipc);

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

	printf("semaccept +++++++++++++++++++++++++ \n");

	//4.循环消费
	while(1){
		//b.P操作 0 号灯
		p_handle(semid,0);
		printf("消费到的消息%s\n",addr);
		//C. V操作 1 号灯
		v_handle(semid,1);
		if(strcmp(addr,"tuichu") == 0){
			break;
		}
	}

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

	//6.删除共享内存
	if(shmctl(ipc,IPC_RMID,NULL) == -1){
		perror("shmctl error");
		return -1;
	}

	//7.删除信号灯
	del_sem(semid);

	return 0;
}




3. 思维导图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值