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

代码

#include <myhead.h>
#include "sem.c"

int main(int argc, const char *argv[])
{
	int rpid1=-1;

	rpid1=fork();

	if(rpid1 > 0)
	{
		int rpid2 = -1;


		rpid2 = fork();

		if(rpid2>0)
		{
			//printf("I am parent process\n");
			//printf("my 1st child process pid=%d\n", rpid1);
			//printf("my 2nd child process pid=%d\n", rpid2);

			char ch = 'A';
			
			// create a  Semaphores setwith 3 sem  
			int semid = create_sem(3); 

			if(semid == -1)
			{
				perror("create_sem error");
				return -1;

			}
			//printf("shmid = %d\n", semid);



			int n = 0;
			while( n++ < 5)
			{
				//printf("n=%d\n", n);

				p(semid, 2); // 2: resources from C
				printf("%c\n", ch);
				v(semid, 0); // release resourcs A

			}




			//recycle child process resources
			wait(NULL);
			wait(NULL);

		}else if(rpid2==0)
		{

			//printf("I am the 2nd child process\n");
			
			char ch = 'B';
			// create a sem

			int semid = create_sem(3); 

			if(semid == -1)
			{
				perror("create_sem error");
				return -1;

			}
			//printf("shmid = %d\n", semid);



			int n = 0;
			while( n++ < 5)
			{
				//printf("n=%d\n", n);

				p(semid, 0); // wait for resources from A
				printf("%c\n", ch);
				v(semid, 1); // release resources B

			}




			//exit process
			exit(EXIT_SUCCESS);

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

		}

	}else if(rpid1==0)
	{
		//printf("I am the 1st child process!\n");
			char ch = 'C';
			// create a sem

			int semid = create_sem(3); //

			if(semid == -1)
			{
				perror("create_sem error");
				return -1;

			}
			//printf("shmid = %d\n", semid);



			int n = 0;
			while( n++ < 5)
			{
				//printf("n=%d\n", n);

				p(semid, 1); // wait for resources B
				printf("%c\n", ch);
				v(semid, 2); // release resources C

			}

			del_sem(semid); // delete Semaphores set 


		
		
		//exit
		exit(EXIT_SUCCESS);


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

	}



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




//init sem 
int init_sem(int semid, int semno)
{
	int val = -1;
	printf("please input No.%d sem init value:", semno);
	scanf("%d", &val);
	getchar();

	//对当前灯进行赋值
	//定义一个共用体
	union semun us;
	us.val = val; //要赋的值

	if(semctl(semid, semno, SETVAL, us) == -1)
	{
		perror("set val erro");
		return -1;
	}

	return 0;

}



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

	//2. create sem by 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. init sem
	for(int i=0; i<semcount; i++)
	{
		//初始化标号为0的灯的value值
		init_sem(semid, i); 	
	}


	//4. return semid 
	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函数
	if( semop(semid, &buf, 1)== -1   )
	{
		perror("p error");
		return -1;
	}
	return 0;

}

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

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

	return 0;



}

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

}

运行结果

ubuntu@ubuntu:~/embedded/04_io/day08$ ./a.out
please input No.0 sem init value:0
please input No.1 sem init value:0
please input No.2 sem init value:1
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C

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

代码

snd

#include <myhead.h>
#include "sem.h" //信号灯集


#define PAGE_SIZE 4096


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


	//1. create a key
	key_t key = ftok("/", 'm');


	if(key == -1)
	{
		perror("ftok error");
		return -1;
	}
	
	printf("key = %#x\n", key);


	//2. create a shared memory through key
	int shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664);
	if(shmid == -1)
	{
		perror("shmget error");;
		return -1;
	}
	printf("shmid = %d\n", shmid);


	//3. mapping shm to user space
	char *addr = (char *)shmat(shmid, NULL, 0);
	//param1: shared memory id
	//param2: NULL -->syastem allocate page address
	//param3: 0--> have rd and wr; SHM_RDONLY--> readonly
	
	if(addr == (void *)-1)
	{
		perror("shmat error");
		return -1;
	
	}
	printf("addr = %p\n", addr);
	//output virtual address
	
	//4. use shared memory
	while(1)
	{
		//p operation
		p(semid, 1); // apply No.1 sem 
		
		printf("please input:");
		fgets(addr, PAGE_SIZE, stdin);
		//store data to shared memory

		addr[strlen(addr) - 1] = 0;
		//rm return
		
		//
		v(semid, 0); // release No. 0 sem
		
		if(strcmp(addr, "quit") == 0)
		{
			break;
		}

	}
	//5. disconnet shm
	if(shmdt(addr) == -1)
	{
		perror("shmdt error");
		return -1;
	
	}

	//6. delete shm
	shmctl(shmid, IPC_RMID, NULL);

	del_sem(semid);
	
	return 0;
}

rcv

#include <myhead.h>
#include "sem.h"

#define PAGE_SIZE 4096


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

	//1. create a key
	key_t key = ftok("/", 'm');
	if(key == -1)
	{
		perror("ftok error");
		return -1;
	}
	
	//2. create a shared memory through key
	int shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664);
	if(shmid == -1)
	{
		perror("shmget error");;
		return -1;
	}
	printf("shmid = %d\n", shmid);


	//3. map shared memory to user space
	char *addr = (char *)shmat(shmid, NULL, 0);
	//param1: shared memory id
	//param2: system allocate page address
	//param3: 0--> have rd and wr; SHM_RDONLY--> readonly
	
	if(addr == (void *)-1)
	{
		perror("shmat error");
		return -1;
	
	}
	printf("addr = %p\n", addr);
	//output virtual address
	
	//4. use shared memory
	while(1)
	{
		p(semid, 0); //apply for No. 0 sem
		printf("shm data=%s\n", addr);
		//read data to shared memory

		v(semid, 1); //release No. 1 sem

		
		if(strcmp(addr, "quit") == 0)
		{
			break;
		}

	}
	

	//5. disconnet shm mapping
	if(shmdt(addr) == -1)
	{
		perror("shmdt error");
		return -1;
	}


	//5. delete shm
	shmctl(shmid, IPC_RMID, NULL);

	//. delete sem
	del_sem(semid);


	return 0;
}

3.思维导图

IO / day08 作业-LMLPHP

12-13 07:39