/*---------------------------------------------------------------------------------------------------------
功能:
父进程产生10个子进程,并打印出子进程产生的随机数的和。要求用信号机制、信号量以及共享内存实现。
思路:
子进程将自己产生的随机数累加到共享内存。当10个子进程都累加完后,用信号机制通知父进程,
父进程就可以从共享内存中读取数据了。为了避免10个子进程向共享内存中写入数据时发生冲突,
应使用信号量进行并发控制。
---------------------------------------------------------------------------------------------------------*/
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/shm.h"
#include "string.h" //NULL 才可以使用
#include "stdlib.h"
union semun
{
int val;
struct semid_ds *buf;
ushort *array;
};
int semid;
int shmid;
char *shm_virtualaddr; //共享内存关联到进程后的虚拟地址
void p(int semid)
{
struct sembuf buf = {0, -1, 0};
semop(semid, &buf, 1);
}
void v(int semid)
{
struct sembuf buf = {0, 1, 0};
semop(semid, &buf, 1);
}
void sigusr1_handler(int n)
{
printf("count = %d, total = %d\n", *(int *)shm_virtualaddr, *(int *)(shm_virtualaddr+4)); //__ 输出共享内存里面保存的count 和total值,前4个字节保存count,后4个字节保存total____
if(semctl(semid, IPC_RMID, 0) == -1) //删除信号量
printf("remove semaphore fail\n");
else
printf("remove semaphore ok\n");
shmdt(shm_virtualaddr); //解除共享内存的关联
if(shmctl(shmid, IPC_RMID, 0) == -1) //删除共享内存
printf("remove shared-memory fail\n");
else
printf("remove shared-memory ok\n");
exit(0);
}
int main()
{
signal(SIGUSR1, sigusr1_handler); //____注册信号处理函数_______
//创建并初始化信号量
semid = semget(IPC_PRIVATE, 1, 0666);
if(semid == -1)
{
printf("create semaphore fail\n");
return 0;
}
else
printf("create semaphore ok\n");
union semun x;
x.val = 1; //_初始化信号量的值为1_ //信号量初值应为多少?
semctl(semid, 0, SETVAL, x);
//创建并关联到共享内存
shmid = shmget(IPC_PRIVATE, 8, 0666); //共享内存一共8字节,前4字节存放count,后4字节存放total
if(shmid == -1)
{
printf("create shared-memory fail\n");
return 0;
}
else
printf("create shared-memory ok\n");
//连接共享内存与某个进程的地址空间
//如果shmat()函数调用成功则返回指向共享内存的指针;否则返回-1.
//第二个参数 Shmaddr是共享内存连接到进程中的存放地址,一般设置为空指针,表示交由系统完成这个工作
shm_virtualaddr = shmat(shmid, 0, 0);
*(int *)shm_virtualaddr = 0; //___将共享内存里面的值设置为0表示count初始值为0_____
*(int *)(shm_virtualaddr+4) = 0; //____ 后4个字节的值设置为0,表示total的值____
char is_child = 0;
int i;
for(i=0; i<10; i++)
{
pid_t pid = fork();
if(pid == 0)
{
is_child = 1; //__创建子进程成功____
break; //___退出子进程所在循环__
}
}
if(is_child)
{
p(semid); //___子进程申请访问共享内存,若申请成功即可访问____
srand(time(NULL) + i);
int num = rand()%10;
(*(int *)shm_virtualaddr)++; //____前面4个字节表示count,每生成一个随机数cont++______
*(int *)(shm_virtualaddr+4) += num; //___后面4个字节是表示total,每次将生成的随机数加上去___
printf("child%d: %d\n", i, num);
v(semid); //___释放信号量,代表已经加上了一个随机数了____
if(*(int *)shm_virtualaddr == 10) //if(_产生的随机数个数已经有10个了_)
kill(getppid(), SIGUSR1); //__那么向父进程发送信号____
}
else
{
while(1)
pause(); //一直等待信号,直到信号来临执行信号处理函数
}
return 0;
}
父进程产生10个子进程,并打印出子进程产生的随机数的和
最新推荐文章于 2022-03-11 14:37:58 发布