网络编程必备知识入门----十个子进程求和
十个子进程求和问题的学习
各位读者朋友好,我是你们的好朋友IT黑铁!今天给大家分享的是我在Linux网络课程学习过程中,思考的第一个有意思的问题。在十个子进程求和中需要使用到的技术有:信号量、信号、共享内存。
如何改进下面这个程序让其使用的共享内存只要一个字节???
#include<stdio.h> #include<stdlib.h> #include"sys/sem.h" #include"sys/types.h" #include"time.h" #include"signal.h" #include"sys/shm.h" #include"unistd.h" union semun{ int val; struct semid_ds *buf; ushort *array; }; int sem_id,shm_id; int* pr; void p(int sem_id) { struct sembuf buf={0,-1,0}; semop(sem_id,&buf,1); } void v(int sem_id) { struct sembuf buf={0,1,0}; semop(sem_id,&buf,1); } void SIGINT_handler(int sql) { int count,total; count=*pr; total=*(pr+1); printf("count=%d,total=%d\n",count,total); semctl(sem_id,IPC_RMID,0); //删除信号量 shmdt(pr); //断开链接 shmctl(shm_id,IPC_RMID,NULL); //删除共享内存 exit(0); } int main() { signal(SIGINT,SIGINT_handler); sem_id=semget(IPC_PRIVATE,1,0666); union semun x; x.val=1; semctl(sem_id,0,SETVAL,x); shm_id=shmget(IPC_PRIVATE,2,0666); pr=(int*)shmat(shm_id,NULL,0); int i,is_child=0; for(i=0;i<10;i++) { int pid=fork(); if(pid==0) { is_child=1; break; } } if(is_child==1) { p(sem_id); int count,num; srand(time(NULL)+getpid()); count=*pr; count=count+1; num=1+rand()/((RAND_MAX+1u)/10); printf("count:%d,num:%d\n",count,num); *pr=count; *(pr+1)=*(pr+1)+num; v(sem_id); if(count==10) { kill(getppid(),SIGINT); } } else { while(1) pause(); } return 0; }
在解决这个问题前,我们先来理理这个程序求和的思路:1.注册一个信号用来在第10个子进程求和完毕后进行父进程输出求和结果 2.创建一个信号量并初始化
用来10个子进程之间对共享内存的并发控制 3.创建一个2个字节的共享内存,一个字节用于存count用于让当前求和进程判断自己是否是最后一个子进程,一个字节用于存和,并绑定在虚拟内存的指针上以便10个子进程访问 4.父进程创建10个子进程后,子进程进行求和,父进程消息循环等待最后一个子进程发来的信号,发来信号后调用信号处理函数完成求和。
在我们只能用一个字节的时候,那么肯定就不能使用count了,这时候我们来想,使用count的作用是得知最后一个子进程并向父进程发送信号,那么我们还能通过其他的方式来得知最后一个子进程是谁吗?起初我想错方向,想要通过数字编码的方式,但一个字节8位,编码实在不可取。后来仔细思索,我们可以完全使用信号量机制,当没有资源时,阻塞住当前进程,直到10个子进程求和完毕后,释放了10个资源使得父进程输出和,这样甚至都不需要使用信号!
#include<stdio.h> #include<stdlib.h> #include"sys/sem.h" #include"sys/types.h" #include"time.h" #include"signal.h" #include"sys/shm.h" #include"unistd.h" union semun{ int val; struct semid_ds *buf; ushort *array; }; int sem_id,shm_id; int* pr; void p_1(int sem_id) { struct sembuf buf={0,-1,0}; semop(sem_id,&buf,1); } void p_2(int sem_id) { struct sembuf buf={1,-10,0}; semop(sem_id,&buf,1); } void v_1(int sem_id) { struct sembuf buf={0,1,0}; semop(sem_id,&buf,1); } void v_2(int sem_id) { struct sembuf buf={1,1,0}; semop(sem_id,&buf,1); } int main() { sem_id=semget(IPC_PRIVATE,2,0666);//定义一个信号量集 union semun x; union semun y; x.val=1; y.val=0; semctl(sem_id,0,SETVAL,x); semctl(sem_id,1,SETVAL,y); shm_id=shmget(IPC_PRIVATE,1,0666); pr=(int*)shmat(shm_id,NULL,0); int i,is_child=0; for(i=0;i<10;i++) { int pid=fork(); if(pid==0) { is_child=1; break; } } if(is_child==1) { p_1(sem_id); int num; srand(time(NULL)+getpid()); num=1+rand()/((RAND_MAX+1u)/10); printf("num:%d\n",num); *pr=num+*pr; v_1(sem_id); v_2(sem_id); } else { p_2(sem_id); int total; total=*pr; printf("total=%d\n",total); semctl(sem_id,IPC_RMID,0); //删除信号量 shmdt(pr); //断开链接 shmctl(shm_id,IPC_RMID,NULL); //删除共享内存 } return 0; } 而在具有忙等待的信号量经典定义下,信号量的值不能为负。 如果信号量的值为负,那么它的绝对值就是等待它的进程数。出现这种情况源于,在实现操作 wait() 时互换了递减和测试的顺序。
以上就是本次十个子进程求和的分享!如有疑问或是指正请评论或私信我,我将及时回复你!