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;
}