操作系统 信号量习题--实例(对上次笔记“经典同步问题”*补充)

课前问题

1.什么是进程?
答:进程是进程实体的运行过程,是系统进行资源的分配与调度的一个单位。(进程实体=数据段+程序段+PCB)

2.理解PCB的作用?
答:进程控制块PCB,它是为了管理计算机中的进程而产生的,它是进程实体的一部分,用于描述进程的当前状况以及进程运行的信息。
系统通过PCB来感知进程的存在,对于中断来说,他可以保护现场,以及恢复现场都要用到PCB;PCB中保存了进程的状态信息,协助进程调度。

3.什么是同步?
答:多个相互合作的进程,在一些关键点上可能需要互相等待或互相交换信息,这种相互制约关系称为进程的同步关系,可以理解为有序

读者写者问题

写者优先方式

分析
读者有限的关键:
若读者先占有互斥信号量,只有当最后一个读者离开,计数降为0时才释放信号量,导致写者弱势

反之写者优先则是,写者先占有某信号量后,直到最后一个写完才释放信号量,读者才能进入

增加一个互斥信号量S,读者和写者都争抢该信号;
对写者也进行计数,第1个写者申请S,其他写者不需要申请S;最后一个写者离开时才释放信号量S.
一旦写者先申请到了S,则所有的读者只能等待写者都走完才可进入共享读。而多个写者通过S后,仍要争抢wmutex信号以完成互斥的写入。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本程序使用Linux操作系统中的信号量机制模拟解决生产者-消费者问题,具体实现如下: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <time.h> #define BUFFER_SIZE 10 #define SHM_KEY 0x1234 #define SEM_KEY 0x5678 union semun { int val; struct semid_ds *buf; unsigned short *array; }; void P(int semid, int index) { struct sembuf sem; sem.sem_num = index; sem.sem_op = -1; sem.sem_flg = SEM_UNDO; semop(semid, &sem, 1); } void V(int semid, int index) { struct sembuf sem; sem.sem_num = index; sem.sem_op = 1; sem.sem_flg = SEM_UNDO; semop(semid, &sem, 1); } int main() { int shmid, semid, i; char *shmaddr; union semun semopts; struct shmid_ds shm_buf; struct sembuf sem; // 创建共享内存 shmid = shmget(SHM_KEY, BUFFER_SIZE, IPC_CREAT | 0666); if (shmid == -1) { perror("shmget error"); exit(EXIT_FAILURE); } // 将共享内存附加到进程的地址空间 shmaddr = (char *)shmat(shmid, NULL, 0); if (shmaddr == (void *)-1) { perror("shmat error"); exit(EXIT_FAILURE); } // 创建信号量 semid = semget(SEM_KEY, 2, IPC_CREAT | 0666); if (semid == -1) { perror("semget error"); exit(EXIT_FAILURE); } // 初始化信号量 semopts.val = BUFFER_SIZE; semctl(semid, 0, SETVAL, semopts); semopts.val = 0; semctl(semid, 1, SETVAL, semopts); // 生产者-消费者模型 for (i = 0; i < 2; i++) { if (fork() == 0) { srand(time(NULL) + i); while (1) { sleep(rand() % 5 + 1); P(semid, 0); printf("Producer %d produced %c\n", i, 'A' + rand() % 26); fflush(stdout); shmaddr[BUFFER_SIZE - semctl(semid, 0, GETVAL, semopts)] = 'A' + rand() % 26; V(semid, 1); } exit(EXIT_SUCCESS); } } for (i = 0; i < 2; i++) { if (fork() == 0) { srand(time(NULL) + i + 2); while (1) { sleep(rand() % 5 + 1); P(semid, 1); printf("Consumer %d consumed %c\n", i, shmaddr[BUFFER_SIZE - semctl(semid, 1, GETVAL, semopts)]); fflush(stdout); shmaddr[BUFFER_SIZE - semctl(semid, 1, GETVAL, semopts)] = ' '; V(semid, 0); } exit(EXIT_SUCCESS); } } // 等待子进程结束 for (i = 0; i < 4; i++) { wait(NULL); } // 删除共享内存和信号量 shmdt(shmaddr); shmctl(shmid, IPC_RMID, &shm_buf); semctl(semid, 0, IPC_RMID, semopts); semctl(semid, 1, IPC_RMID, semopts); return 0; } ``` 程序中使用了共享内存和信号量来实现生产者-消费者模型。其中,共享内存用于存储生产者生产的数据和消费者消费的数据,信号量用于实现生产者和消费者之间的同步和互斥。 具体实现过程如下: 1. 创建共享内存,将其附加到进程的地址空间中。 2. 创建两个信号量,一个用于表示缓冲区中空闲的位置数,另一个用于表示缓冲区中已经存放的数据数。 3. 初始化信号量,将空闲位置数设置为缓冲区大小,将已经存放的数据数设置为0。 4. 创建两个生产者和两个消费者进程,每个进程都会不断地生产或消费数据。 5. 在生产者进程中,先等待一段时间,然后获取空闲位置数的信号量,将生产的数据存放到缓冲区中,释放已经存放的数据数的信号量。 6. 在消费者进程中,先等待一段时间,然后获取已经存放的数据数的信号量,从缓冲区中取出数据,将空闲位置数的信号量加1。 7. 等待所有子进程结束后,删除共享内存和信号量

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值