📄 test13_a.c
字号:
#include "test13.h"void fun_init(int *psem_id, int *pshm_id1, int *pshm_id2, int *pshm_id3, char **pshm_addr1, char **pshm_addr2);void child_write(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2);void child_read(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2, int num);void resource_free(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2);void sig_kill();void sig_pause();int b_kill, b_pause; /*用于判断进程是否被要求退出或暂停*/struct PInfo *shm_addr3; /*共享内存3的首地址*/int main(){ int sem_id, shm_id1, shm_id2, shm_id3; char *shm_addr1, *shm_addr2; /*共享内存1、2的首地址*/ int pid; int i, j; int sta; fun_init(&sem_id, &shm_id1, &shm_id2, &shm_id3, &shm_addr1, &shm_addr2); /*初始化函数,创建信号量和共享内存*/ for(i=0; i<27; i++) shm_addr1[i] = '\0'; /*将共享内存1的内容初始化成'\0'*/ for(i=0; i<4; i++) for(j=0; j<27; j++) shm_addr2[i*27 + j] = '\0'; /*将共享内存2的内容初始化成'\0'*/ if((pid=fork()) == -1) /*创建一个写进程*/ { printf("fork faild !!!\n"); exit(0); } if(!pid) { b_kill = 0; b_pause = 0; signal(16, sig_kill); /*定义要求进程退出运行的软中断处理函数*/ signal(17, sig_pause); /*定义要求进程暂停的软中断处理函数*/ child_write(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); /*向共享内存1写字母的功能函数*/ } else { for(i=1; i<=4; i++) /*创建4个读进程*/ { pid = fork(); switch(pid) { case -1: printf("fork faild !!!\n"); exit(0); case 0 : b_kill = 0; b_pause = 0; signal(16, sig_kill); signal(17, sig_pause); child_read(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2, i); exit(0); /*从共享内存1读字母,将其写入共享内存2中各自对应区域*/ default: break; } } if(shmdt(shm_addr1) == -1) /*与共享内存断开*/ printf("shmdt faild !!!\n"); if(shmdt(shm_addr2) == -1) printf("shmdt faild !!!\n"); exit(0); }}/*void fun_init(int *psem_id, int *pshm_id1, int *pshm_id2, int *pshm_id3, char ** pshm_addr1, char **pshm_addr2)返回值:无参数:psem_id, int型指针,用于将创建的信号量集的ID返回给调用函数。 pshm_id1, int型指针,用于将创建的共享内存1的ID返回给调用函数。 pshm_id2, int型指针,用于将创建的共享内存2的ID返回给调用函数。 pshm_id3, int型指针,用于将创建的共享内存3的ID返回给调用函数。 pshm_addr1 char *型指针,用于将共享内存1的首地址返回给调用函数。 pshm_addr2 char *型指针,用于将共享内存2的首地址返回给调用函数。函数功能:创建一个包含3个信号量的信号量集,并创建3块共享内存。*/void fun_init(int *psem_id, int *pshm_id1, int *pshm_id2, int *pshm_id3, char ** pshm_addr1, char **pshm_addr2){ int sta; union semun sem_v; *psem_id = semget(SEM_KEY, 3, IPC_CREAT|0600); if(*psem_id == -1) { printf("semget faild !!!\n"); exit(0); } *pshm_id1 = shmget(SHM1_KEY, 27, IPC_CREAT|0600); if(*pshm_id1 == -1) { printf("shmget faild !!!\n"); exit(0); } *pshm_id2 = shmget(SHM2_KEY, 27*4, IPC_CREAT|0600); if(*pshm_id2 == -1) { printf("shmget faild !!!\n"); exit(0); } *pshm_id3 = shmget(SHM3_KEY, sizeof(struct PInfo)*5, IPC_CREAT|0600); if(*pshm_id3 == -1) { printf("shmget faild !!!\n"); exit(0); } sem_v.val = 2; sta = semctl(*psem_id, 0, SETVAL, sem_v); if(sta == -1) { printf("semctl faild !!!\n"); exit(0); } sem_v.val = 4; sta = semctl(*psem_id, 1, SETVAL, sem_v); if(sta == -1) { printf("semctl faild !!!\n"); exit(0); } sem_v.val = 1; sta = semctl(*psem_id, 2, SETVAL, sem_v); if(sta == -1) { printf("semctl faild !!!\n"); exit(0); } *pshm_addr1 = shmat(*pshm_id1, 0, 0); if(!(*pshm_addr1)) { printf("shmat faild !!!\n"); exit(0); } *pshm_addr2 = shmat(*pshm_id2, 0, 0); if(!(*pshm_addr2)) { printf("shmat faild !!!\n"); exit(0); } }/*void child_write(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2)返回值:无参数:sem_id, int型,信号量集的ID。 shm_id1 int型,共享内存1的ID。 shm_id2 int型,共享内存2的ID。 shm_id3 int型,共享内存3的ID。 shm_addr1 char型指针,共享内存1的首地址。 shm_addr2 char型指针,共享内存2的首地址。函数功能:向共享内存1写入26个英文字母,并在写进程结束运行时,调用resource_free()函数, 使写进程与共享内存脱离,并在没有其他进程与共享内存相连时,销毁共享内存与信号量集。*/void child_write(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2){ int sta; int i; struct sembuf sem_b[2]; shm_addr3 = shmat(shm_id3, 0, 0); if(!shm_addr3) { printf("shmat faild in child_write() !!!\n"); exit(0); } srand((int)time(0)); shm_addr3[0].pid = getpid(); shm_addr3[0].pstatus = 'R'; sem_b[0].sem_num = 0; sem_b[0].sem_flg = SEM_UNDO; sem_b[1].sem_num = 2; sem_b[1].sem_flg = SEM_UNDO; for(i=0; i<26; i++) { if(b_kill) { resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); } if(b_pause) pause(); sem_b[0].sem_op = -2; sem_b[1].sem_op = -1; shm_addr3[0].pstatus = 'V'; sta = semop(sem_id, sem_b, 2); if(sta == -1) { printf("semop faild in child_write() !!!\n"); shm_addr3[0].pstatus = 'X'; resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); } shm_addr3[0].pstatus = 'R'; shm_addr1[i] = 'a'+i; sleep(2); sem_b[0].sem_op = 2; sem_b[1].sem_op = 1; sta = semop(sem_id, sem_b, 2); if(sta == -1) { printf("semop faild in child_write() !!!\n"); shm_addr3[0].pstatus = 'X'; resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); } sleep(1); } shm_addr3[0].pstatus = 'F'; resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2);}/*void child_read(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2, int num)返回值:无参数:sem_id, int型,信号量集的ID。 shm_id1 int型,共享内存1的ID。 shm_id2 int型,共享内存2的ID。 shm_id3 int型,共享内存3的ID。 shm_addr1 char型指针,共享内存1的首地址。 shm_addr2 char型指针,共享内存2的首地址。 num int型,取值范围{1,2,3,4},用于对读进程的识别函数功能:从共享内存1读取字符,并将其写入共享内存2中各个读进程各自对应的区域。 在读进程结束时,调用resource_free()函数,读进程与共享内存脱离,并在没有其他进程与共享内存相连时,销毁共享内存与信号量集。*/ void child_read(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2, int num){ struct sembuf sem_b[2]; int sta; int i; shm_addr3 = shmat(shm_id3, 0, 0); if(!shm_addr3) { printf("shmat faild in child_read() !!!\n"); exit(0); } srand(300*num + (int)time(0)); shm_addr3[num].pid = getpid(); shm_addr3[num].pstatus = 'R'; sem_b[0].sem_num = 0; sem_b[0].sem_flg = SEM_UNDO; sem_b[1].sem_num = 1; sem_b[1].sem_flg = SEM_UNDO; for(i=0; i<26; i++) { if(b_kill) { resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); } if(b_pause) pause(); sem_b[0].sem_op = -1; sem_b[1].sem_op = -1; shm_addr3[num].pstatus = 'V'; sta = semop(sem_id, sem_b, 2); if(sta == -1) { printf("semop faild in child_read()!!!\n"); resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); shm_addr3[num].pstatus = 'X'; exit(0); } shm_addr3[num].pstatus = 'R'; if(shm_addr1[i] != '\0') shm_addr2[27*(num-1) + i] = shm_addr1[i]; else i--; sem_b[0].sem_op = 1; sem_b[1].sem_op = 1; sta = semop(sem_id, sem_b, 2); if(sta == -1) { printf("semop faild in child_read()!!!\n"); shm_addr3[num].pstatus = 'X'; resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2); exit(0); } sleep((rand()%5)+1); } shm_addr3[num].pstatus = 'F'; resource_free(sem_id, shm_id1, shm_id2, shm_id3, shm_addr1, shm_addr2);}/*void resource_free(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2)返回值:无参数:sem_id, int型,信号量集的ID。 Shm_id1 int型,共享内存1的ID。 Shm_id2 int型,共享内存2的ID。 Shm_id3 int型,共享内存3的ID。 Shm_addr1 char型指针,共享内存1的首地址。 Shm_addr2 char型指针,共享内存2的首地址。函数功能:在每个读写进程退出时被调用,用于调用进程的与共享内存脱离,若没有其他进程与共享内存相连,则销毁共享内存与信号量集。*/void resource_free(int sem_id, int shm_id1, int shm_id2, int shm_id3, char *shm_addr1, char *shm_addr2){ int k; int sta; struct shmid_ds shm_buf; k=0; if(shmdt(shm_addr1) == -1) printf("shmdt faild in resource_free() !!!\n"); sta = shmctl(shm_id1, IPC_STAT, &shm_buf); if(sta == -1) printf("shmctl faild in resource_free() !!!\n"); else { if(shm_buf.shm_nattch == 0) { k++; sta = shmctl(shm_id1, IPC_RMID, 0); if(sta == -1) printf("shmctl faild in resource_free() !!!\n"); } } if(shmdt(shm_addr2) == -1) printf("shmdt faild in resource_free() !!!\n"); sta = shmctl(shm_id2, IPC_STAT, &shm_buf); if(sta == -1) printf("shmctl faild in resource_free() !!!"); else { if(shm_buf.shm_nattch == 0) { k++; sta = shmctl(shm_id2, IPC_RMID, 0); if(sta == -1) printf("shmctl faild in resource_free() !!!\n"); } } if(shmdt(shm_addr3) == -1) printf("shmdt faild in resource_free() !!!\n"); sta = shmctl(shm_id3, IPC_STAT, &shm_buf); if(sta == -1) printf("shmctl faild in resource_free() !!!\n"); else { if(shm_buf.shm_nattch == 0) { k++; sta = shmctl(shm_id3, IPC_RMID, 0); if(sta == -1) printf("shmctl faild in resource_free() !!!\n"); } } if(k == 3) { sta = semctl(sem_id, 3, IPC_RMID, 0); if(sta == -1) printf("semctl faild in resource_free() !!!\n"); }}/*void sig_kill()返回值:无参数: 无函数功能:收到监控程序发来的结束进程运行的信号时,所执行的软中断处理函数。*/void sig_kill(){ int i; b_kill = 1; for(i=0; i<=4; i++) if(shm_addr3[i].pid == getpid()) break; shm_addr3[i].pstatus = 'X';}/*void sig_pause()返回值:无参数: 无函数功能:收到监控程序发来的暂停进程运行的信号时,所执行的软中断处理函数。*/void sig_pause(){ int i; for(i=0; i<=4; i++) if(shm_addr3[i].pid == getpid()) break; if(b_pause == 0) { b_pause = 1; shm_addr3[i].pstatus = 'P'; } else { b_pause = 0; shm_addr3[i].pstatus = 'R'; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -