Linux IPC实践(12)

实践1:信号量实现进程互斥

父子进程执行流程如下:

父进程

子进程

P

P

O(print)

X(print)

sleep

sleep

O(print)

X(print)

V

V

sleep

sleep

从图中可以看出,O或X总是成对出现的,要么两个O,要么两个X;

/**P,V原语实现父子进程互斥使用终端**/// 程序代码int main(int argc,char *argv[]){int semid = sem_create(IPC_PRIVATE);sem_setval(semid, 1);int count = 10;pid_t pid = fork();if (pid == -1)err_exit("fork error");else if (pid > 0) //子进程{srand(getpid());while (count –){sem_P(semid);//临界区开始cout << ‘X’;fflush(stdout); //一定要加上ffflush, 因为中断是行缓冲的sleep(rand()%3);cout << ‘X’;fflush(stdout);//临界区结束sem_V(semid);sleep(rand()%3);}}else//父进程{srand(getpid());while (count –){sem_P(semid);//临界区开始cout << ‘O’;fflush(stdout);sleep(rand()%3);cout << ‘O’;fflush(stdout);//临界区结束sem_V(semid);sleep(rand()%3);}wait(NULL);sem_delete(semid);}return 0;}

实践2:信号量集解决哲学家进餐问题

假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,,思考的时候也停止吃东西。每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃饭,所以假设哲学家必须用两只餐叉吃东西,而且他们只能使用自己左右手边的那两只餐叉。

/** 解决的方法采用的是: 只有左右两个刀叉都能够使用时,才拿起两个刀叉实现了有死锁和无死锁的两种形式的wait_2fork(见下)**/int semid;//没有死锁的waitvoid wait_2fork(unsigned short no){unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops[2] = {{left, -1, 0}, {right, -1, 0}};//同时获取左右两把刀叉if (semop(semid, sops, 2) == -1)err_exit("wait_2fork error");}/*//有死锁的waitvoid wait_2fork(unsigned short no){unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops = {left, -1, 0};//获取左边的刀叉if (semop(semid, &sops, 1) == -1)err_exit("wait_2fork error");sleep(4); //沉睡几秒, 加速死锁的产生sops.sem_num = right;//获取右边的刀叉if (semop(semid, &sops, 1) == -1)err_exit("wait_2fork error");}*///释放两把刀叉void signal_2fork(unsigned short no){unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops[2] = {{left, 1, 0}, {right, 1, 0}};if (semop(semid, sops, 2) == -1)err_exit("signal_2fork error");}//哲学家void philosopher(unsigned short no){srand(time(NULL));while (true){cout << no << " is thinking" << endl;sleep(rand()%5+1);cout << no << " is hunger" << endl;wait_2fork(no); //获取两把刀叉//进餐cout << "++ " << no << " is eating" << endl;sleep(rand()%5+1);signal_2fork(no);//释放两把刀叉}}int main(){// 创建一个信号量集: 里面包含5个信号量semid = semget(IPC_PRIVATE, 5, IPC_CREAT|0666);if (semid == -1)err_exit("semget error");//将每个信号量都设初值为1union semun su;su.val = 1;for (int i = 0; i < 5; ++i)if (semctl(semid, i, SETVAL, su) == -1)err_exit("semctl SETVAL error");//创建四个子进程, 将每个进程的编号设定为nopid_t pid;unsigned short no = 0;for (unsigned short i = 0; i < 4; ++i){pid = fork();if (pid == -1)err_exit("fork error");else if (pid == 0){no = i+1;break;}}// 最后五个进程(4个子进程+1个父进程)都会汇集到此处,// 每个进程代表着一个哲学家,编号no: 0~4philosopher(no);return 0;}

再长的路,一步步也能走完,再短的路,不迈开双脚也无法到达。

Linux IPC实践(12)

相关文章:

你感兴趣的文章:

标签云: