织梦CMS - 轻松建站从此开始!

罗索

Linux IPC机制的例子

jackyhwei 发布于 2011-07-12 17:49 点击:次 
Linux的IPC机制(进程间通信)在系统编程的书里面总是会提到...想必很多人也在看..这里贴出一个我写的简单的例子..
TAG:

Linux的IPC机制(进程间通信)在系统编程的书里面总是会提到...想必很多人也在看..这里贴出一个我写的简单的例子..

semtest1.c包含了信号量、信号处理、共享内存三种操作..这里实现的功能很简单..就是直接让两个进程通信方式是共享内容,读写同步有名信号量实现的过程中,可以在shell下使用ipcs命令查看函数运行不同时刻,共享内存和信号量的信息,验证函数的作用。

  1. #include<stdio.h> 
  2. #include<unistd.h> 
  3. #include<sys/sem.h> 
  4. #include<stdlib.h> 
  5. #include<errno.h> 
  6. #include<string.h> 
  7. #include<sys/types.h> 
  8. #include<sys/ipc.h> 
  9. #include<signal.h> 
  10.  
  11. #define FULL 1 
  12. #define EMPTY 0 
  13. #define KEY 33 
  14. union semun { 
  15.   int              val;    /* Value for SETVAL */ 
  16.   struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */ 
  17.   unsigned short  *array;  /* Array for GETALL, SETALL */ 
  18.   struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */ 
  19. }; 
  20.  
  21. //关于union semun的定义可以man semctl,其中有如下说明: 
  22. //This function has three or four arguments,  depend- 
  23. //ing  on  cmd.   When there are four, the fourth has 
  24. //the type union semun.   The  calling  program  must 
  25. //define this union as follows: 
  26. //union semun { 
  27. //  int              val;    /* Value for SETVAL */ 
  28. //  struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */ 
  29. //  unsigned short  *array;  /* Array for GETALL, SETALL */ 
  30. //  struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */ 
  31. //在不同版本的unix中,上述union结构略有不同, 
  32. //而且必须在程序中定义出来,因为头文件中并没有包含该定义。 
  33.  
  34. void sighandler(int signumber); 
  35. void shdel(void); 
  36. int server(void); 
  37. int client(int shmid); 
  38. int semlock(int semid,int semnum); 
  39. int semunlock(int semid,int semnum); 
  40. int delsemid,delshmid; 
  41.  
  42. int main(int argc,char *argv[]) 
  43.   if(argc==1) 
  44.   {server();} 
  45.   else if(argc==2) 
  46.   {client(atoi(argv[1]));} 
  47.   
  48.   //首先运行server,然后根据显示的shmid, 
  49.   //以shmid为参数,运行client... 
  50.   //atoi(argv[1])是把char型的字符串转换为int 
  51.   
  52.   return 0; 
  53.  
  54. int server(void
  55.   if(signal(SIGINT,&sighandler)==SIG_ERR) 
  56.   {fprintf(stderr,"register SIGINT handler error...\n");exit(0);} 
  57. //创建一个信号量集,包含两个shaphore,用来阻塞写进程和读进程; 
  58.   int semid=semget(IPC_PRIVATE,2,IPC_CREAT|0660); 
  59.   union semun semset; 
  60.   semset.val=1; 
  61.   if(semctl(semid,EMPTY,SETVAL,semset)==-1) 
  62.   {fprintf(stderr,"semctl error! \nexiting ..\n");exit(0);}
  63. //“空信号量”使得资源可以使用 
  64.   semset.val=0; 
  65.  
  66.   if(semctl(semid,FULL,SETVAL,semset)==-1) 
  67.   {fprintf(stderr,"semctl error! \nexiting ...\n");exit(0);}
  68. //“满信号量”使得资源使用时进程阻塞 
  69.  
  70. /**********简单测试***********/ 
  71. //  struct semid_ds semds; 
  72. //  union semun semset; 
  73. //  semset.buf=&semds; 
  74. //  if(semctl(semid,2,IPC_STAT,semset)==-1) 
  75. //  { 
  76. //    fprintf(stderr,"semctl error!\n"); 
  77. //    exit(0); 
  78. //  } 
  79. // printf("key of sme0=%d\n",semset.buf->sem_perm.__key); 
  80. // printf("mode of sem=%4o\n",semset.buf->sem_perm.mode); 
  81. // 注意,不同版本的unix系统中,ipc_perm当中的参量名可能不同,也需要man手册中查询 
  82.   int shmid=shmget(KEY,128,IPC_CREAT|0660); 
  83.   if(shmid<0) 
  84.   {fprintf(stderr,"shared memory open error\n");exit(0);} 
  85.   void *shmdata; 
  86.   shmdata=shmat(shmid,0,0); 
  87.   if(shmdata==(void*)-1) 
  88.   {fprintf(stderr,"shmat error!\nexiting...\n");exit(0);} 
  89.   *(int*)shmdata=semid; 
  90.   char *buf=shmdata+sizeof(semid); 
  91.   printf("server is running with shmid:%d\n\n\n",shmid); 
  92.   delsemid=semid; 
  93.   delshmid=shmid; 
  94.   atexit(&shdel); 
  95.   //程序退出时,会删除信号量和共享内存 
  96.   while(1) 
  97.   { 
  98.     printf("waiting until buf is full.\n"); 
  99.     fflush(stdout); 
  100.     semlock(semid,FULL); 
  101.     printf("buf is full,message:"); 
  102.     printf("%s\n",buf); 
  103.     semunlock(semid,EMPTY); 
  104.   } 
  105.   return 0; 
  106.  
  107. int client(int shmid) 
  108.   int semid; 
  109.   char *buf; 
  110.   void *shmptr; 
  111.   shmptr=shmat(shmid,0,0); 
  112.   if(shmptr==(void*)-1) 
  113.   {printf("client shmat error...\n");exit(0);} 
  114.   
  115.   semid=*(int*)shmptr; 
  116.   buf=shmptr+sizeof(semid); 
  117.  
  118.   while(1) 
  119.   { 
  120.    printf("ready to write,waiting message read...\n...\n\n"); 
  121.    semlock(semid,EMPTY); 
  122.    printf("Message's read...\ninput new message:"); 
  123.    fgets(buf,128-sizeof(semid),stdin); 
  124.    semunlock(semid,FULL); 
  125.   } 
  126.  
  127. int semlock(int semid,int semnum) 
  128.   //根据semop()的操作规则 
  129.   //函数给信号量semaphore减1,信号量>=1,那么无等待, 
  130.   //否则阻塞,直到semaphore置大于等于1; 
  131.   struct sembuf op; 
  132.   op.sem_num=semnum; 
  133.   op.sem_op=-1; 
  134.   op.sem_flg=0; 
  135.   semop(semid,&op,1); 
  136.  
  137. int semunlock(int semid,int semnum) 
  138.   //根据semop()的规则,函数将会给semaphre的值增加1,操作无等待,函数立即返回. 
  139.   struct sembuf op; 
  140.   op.sem_num=semnum; 
  141.   op.sem_op=1; 
  142.   op.sem_flg=0; 
  143.   semop(semid,&op,1); 
  144.  
  145. void sighandler(int signumber) 
  146.   printf("program is exiting...\n"); 
  147.   exit(0); 
  148.  
  149. void shdel() 
  150.   shmctl(delshmid,IPC_RMID,0); 
  151.   semctl(delsemid,0,IPC_RMID); 

 

(jackyhwei)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201107/14706.html]
本文出处:未知 作者:jackyhwei
顶一下
(29)
96.7%
踩一下
(1)
3.3%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容