大概在很久之前就一直关注的ipc问题因为一直没有怎么使用也不是很明了,实在是为了自己的懒惰而汗颜了。经典的ipc里面除了自己曾经用到过的 pthread_mutex之外,对其他的几种都不了解。自己学习的话也说了不少,可是都没有什么效果,看书似乎都看不动。
最近整理了一下几种ipc方式的使用,一些小问题,在此存档:
一.posix的msgqueue的支持问题。
要说明的是从一开始就觉得所谓的posix的兼容是很好的一个东西,而linux对posix的兼容性很好也是一直以来发展linuxer的一个重要的游 说砝码。但是在开始测试posix message queue的时候遭到了当头一棒。程序编译通过,连接出错!然后google到nptl的知识,声称posix msgqueue的支持在mm分支中发展。晕先。不甘心的同时在新下载的2.6.18里面发现了如下说明:
2.6.18的内核里面关于posix message-queue的选项说明:
CONFIG_POSIX_MQUEUE:
POSIX variant of message queues is a part of IPC. In POSIX message
queues every message has a priority which decides about succession
of receiving it by a process. If you want to compile and run
programs written e.g. for Solaris with use of its POSIX message
queues (functions mq_*) say Y here. To use this feature you will
also need mqueue library, available from
<http://www.mat.uni.torun.pl/~wrona/posix_ipc/>
POSIX message queues are visible as a filesystem called 'mqueue'
and can be mounted somewhere if you want to do filesystem
operations on message queues.
If unsure, say Y.
Symbol: POSIX_MQUEUE [=y]
Prompt: POSIX Message Queues
Defined at init/Kconfig:118
Depends on: NET && EXPERIMENTAL
同时在2.6.16里面这个还是没有的,真是庆幸啊,要是早点开始关注这个岂不是要郁闷很久或者麻烦很久。遵照上面内核编译系统给出的信息,上网站一看原 来已经转到了:http://www.geocities.com/wronski12/posix_ipc/index.html.下载了: libmqueue-4.41.tar.gz。经典的三步之后再编译。bingle!
程序清单:posixqueue.c
#include <mqueue.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <errno.h>#define MSGQUEUE_NAME "/tllmsgqueue"#define MAXMSGNAMELENGTH 32#define MSGQUEUE_LENGTH 128#define MSG_LENGTH 64struct parameters{ char msgQueueName[MAXMSGNAMELENGTH]; struct mq_attr msgattr; unsigned int timeInterval;};void msgSendThread(void * data){ //pthread_detach(pthread_self()); struct parameters * para=(struct parameters *)data; mq_unlink(para->msgQueueName); mqd_t mqid; char buffer[MSG_LENGTH]={0}; unsigned int counter=0; mode_t mode; mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; mqid=mq_open(para->msgQueueName,para->msgattr.mq_flags,mode,&(para->msgattr)); if(mqid == -1) { switch(errno) { case EACCES: printf("EACCES------------/n"); break; case EEXIST: printf("EEXIST------------/n"); break; case EINTR: printf("EINTR------------/n"); break; case EINVAL: printf("EINVAL------------/n"); break; case ENAMETOOLONG: printf("ENAMETOOLONG------------/n"); case ENOENT: printf("ENOENT------------/n"); break; case ENOMEM: printf("ENOMEM------------/n"); break; case ENOSPC: printf("ENOSPC------------/n"); break; case EFAULT: printf("EFAULT------------/n"); break; case EMFILE: printf("EMFILE------------/n"); break; case ENFILE: printf("ENFILE------------/n"); break; default: break; } printf("SendThread:open msqueue failed!/n"); return; } for(;counter<10;counter++) { sprintf(buffer,"this is the #%d message",counter); mq_send(mqid,buffer,MSG_LENGTH,0); printf("send out message:%s./n",buffer); sleep(1); } memset(buffer,0,MSG_LENGTH); sprintf(buffer,"quit"); mq_send(mqid,buffer,MSG_LENGTH,0); mq_close(mqid); printf("now send thread quit./n"); return;}void msgReceiveThread(void * data){ //pthread_detach(pthread_self()); struct parameters * para=(struct parameters *)data; mqd_t mqid; struct mq_attr privateAttr; char buffer[MSG_LENGTH]={0}; mode_t mode; mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; mqid=mq_open(para->msgQueueName,para->msgattr.mq_flags,mode,&(para->msgattr)); if(mqid == -1) { switch(errno) { case EACCES: printf("EACCES------------/n"); break; case EEXIST: printf("EEXIST------------/n"); break; case EINTR: printf("EINTR------------/n"); break; case EINVAL: printf("EINVAL------------/n"); break; case ENAMETOOLONG: printf("ENAMETOOLONG------------/n"); case ENOENT: printf("ENOENT------------/n"); break; case ENOMEM: printf("ENOMEM------------/n"); break; case ENOSPC: printf("ENOSPC------------/n"); break; case EFAULT: printf("EFAULT------------/n"); break; case EMFILE: printf("EMFILE------------/n"); break; case ENFILE: printf("ENFILE------------/n"); break; default: break; } printf("ReceiveThread:open msqueue failed!/n"); return; } unsigned int nreads=0; for(;;) { mq_getattr(mqid,&privateAttr); while(privateAttr.mq_curmsgs>0) {cread: nreads=mq_receive(mqid,buffer,MSG_LENGTH,NULL); if(strncmp(buffer,"quit",4) ==0 ) { goto rend; } printf("/t/tread %d bytes,message is:%s./n",nreads,buffer); mq_getattr(mqid,&privateAttr); } goto cread; }rend: mq_unlink(para->msgQueueName); mq_close(mqid); printf("now receive thread quit./n"); return;}int main(void){ struct parameters myPara; memset((void *)&myPara,0,sizeof(struct parameters)); strncat(myPara.msgQueueName,MSGQUEUE_NAME,MAXMSGNAMELENGTH); //myPara.msgattr.mq_flags=O_RDWR|O_CREAT|O_NONBLOCK; myPara.msgattr.mq_flags=O_RDWR|O_CREAT; myPara.msgattr.mq_maxmsg=MSGQUEUE_LENGTH; myPara.msgattr.mq_msgsize=MSG_LENGTH; myPara.msgattr.mq_curmsgs=0; myPara.timeInterval=1; pthread_t pids; pthread_t pidr; pthread_create(&pids,NULL,(void *)msgSendThread,&myPara); pthread_create(&pidr,NULL,(void *)msgReceiveThread,&myPara); pthread_join(pids,NULL); pthread_join(pidr,NULL); printf("now main thread quit./n"); return 0;}
二.mmap的问题:
因为前面的posix的消息队列的问题慢慢就觉得posix毕竟还是不如sysV在unix系列的操作系统上来得通用,然后先把sysV的ipc方式都试 用了一遍再试用posix方式的时候,犯了思维惯性的错误。因为sysV的share memory方式是“自动扩展”的(或者是达到一种“自动扩展”的效果),所以在试用posix方式shm的时候没有注意mmap是不具备“自动扩展”功 能的,所以就一直卡在“总线错误”这个运行错误上。其实说起来这个错误提示也是有点怪,google了很久也没有明确的说明。好在最后还是搞定了。
程序清单:posixshm.c
#include <sys/types.h>#include <semaphore.h>#include <sys/mman.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <mqueue.h>#include "myerr.h"#define SEM_WRITER "/tmptestllsemw"#define SEM_READER "/tmptestllsemr"#define SHM_NAME "/tmptestllshm"#define SHMSIZE 64struct ThreadPara{ sem_t * reader; sem_t * writer; int shmid; int shmsize;};void writerThread(void * data){ unsigned int counter=0; struct ThreadPara * myPa=(struct ThreadPara *)data; char * buffer; buffer=mmap(NULL,myPa->shmsize,PROT_READ|PROT_WRITE,MAP_SHARED,myPa->shmid,0); printf("writer:get buffer address is:%x./n",(unsigned int)buffer); for(counter=0;counter<10;counter++) { sem_wait(myPa->writer); sprintf((char *)buffer,"this is the posix shm #%d message",counter); sem_post(myPa->reader); sleep(1); } sem_wait(myPa->writer); memset(buffer,0,myPa->shmsize); sprintf(buffer,"quitnow"); sem_post(myPa->reader); munmap(buffer,myPa->shmsize); printf("now send thread quit./n"); return;}void readerThread(void * data){ struct ThreadPara * myPa=(struct ThreadPara *)data; void * buffer; buffer=mmap(NULL,myPa->shmsize,PROT_READ|PROT_READ,MAP_SHARED,myPa->shmid,0); printf("reader:get buffer address is:%x./n",(unsigned int )buffer); for(;;) { sem_wait(myPa->reader); if(strncmp((char *)buffer,"quitnow",7) == 0) { break; } printf("/tYes,i got buffer:%s./tthis is shm realization./n",(char *)buffer); sem_post(myPa->writer); } munmap(buffer,myPa->shmsize); printf("now receive thread quit./n"); return;}int main(void){ struct ThreadPara myPara; int oFlag; mode_t oMode; memset(&myPara,0,sizeof(struct ThreadPara)); oFlag=O_CREAT; oMode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; sem_unlink(SEM_READER); sem_unlink(SEM_WRITER); myPara.reader=sem_open(SEM_READER,oFlag,oMode,0); if(myPara.reader <= 0) { printf("get semr err!/n"); judgeErr(errno); goto cleanup; } myPara.writer=sem_open(SEM_WRITER,oFlag,oMode,1); if(myPara.writer <= 0) { printf("get semw err!/n"); judgeErr(errno); goto cleanup; } oFlag=O_CREAT|O_RDWR; myPara.shmid=shm_open(SHM_NAME,oFlag,oMode); if(myPara.shmid < 0) { printf("get shm err!/n"); judgeErr(errno); goto cleanup; } printf("shmid:%d./n",myPara.shmid); if(lseek(myPara.shmid,SHMSIZE-1,SEEK_SET)<0) { printf("lseek error./n"); } if(write(myPara.shmid,"",1)!=1) { printf("write error./n"); } myPara.shmsize=SHMSIZE; pthread_t pidr; pthread_t pidw; pthread_create(&pidr,NULL,(void *)readerThread,&myPara); pthread_create(&pidw,NULL,(void *)writerThread,&myPara); pthread_join(pidr,NULL); pthread_join(pidw,NULL);cleanup: sem_unlink(SEM_READER); sem_unlink(SEM_WRITER); shm_unlink(SHM_NAME); printf("main thread quit now./n"); return 0;}
三.如果是简单的信号量的使用的话还是posix的信号量用起来简单一些,和mutex有点象吧。
最 后:其他没什么问题。一些说明就是虽然这里说的ipc的问题,但是到底是将多个工作流程实现为多进程,还是将多个工作流程实现为多线程。还是具体问题具体 分析吧,比如考虑到实时性,考虑的进程轮换的开销等等,不过大致的想来似乎是一样,按照“内核线程”的模型,多线程似乎还节省了进程切换的开销呢。呵呵。 先这么臆断吧,也不知道是不是正确的,有机会测试一下。
而这里图个方便,就全部都是采用开线程测试的。也是做个备忘的意思,几个程序的清单如下:
sysvqueue.c
#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <errno.h>#define MSGQUEUE_NAME "/tmp/tllmsgqueue"#define MSGQUEUE_ID 0#define MAXMSGNAMELENGTH 32#define MSGQUEUE_LENGTH 128#define MSG_LENGTH 64struct parameters{ key_t mqid; struct msqid_ds qds; int oflag;};void msgSendThread(void * data){ //pthread_detach(pthread_self()); struct parameters * para=(struct parameters *)data; int mqid; char buffer[MSG_LENGTH]={0}; unsigned int counter=0; mqid=msgget(para->mqid,para->oflag); if(mqid == -1) { return; } for(;counter<10;counter++) { sprintf(buffer,"this is the #%d message",counter); msgsnd(mqid,buffer,MSG_LENGTH,0); sleep(1); } memset(buffer,0,MSG_LENGTH); sprintf(buffer,"quit"); msgsnd(mqid,buffer,MSG_LENGTH,0); //msgctl(mqid,IPC_RMID,NULL); printf("send thread quit now./n"); return;}void msgReceiveThread(void * data){ //pthread_detach(pthread_self()); struct parameters * para=(struct parameters *)data; int mqid; char buffer[MSG_LENGTH]={0}; mqid=msgget(para->mqid,para->oflag); if(mqid == -1) { return; } unsigned int nreads=0; for(;;) { msgctl(mqid,IPC_STAT,&(para->qds)); while(para->qds.msg_qnum>0) {doread: nreads=msgrcv(mqid,buffer,MSG_LENGTH,0,0); if(errno == EIDRM) { goto abquit; } if(strncmp(buffer,"quit",4)==0) { goto endreceive; } printf("read %hd bytes,message is:%s./n",nreads,buffer); msgctl(mqid,IPC_STAT,&(para->qds)); } goto doread; }endreceive: msgctl(mqid,IPC_RMID,NULL);abquit: printf("receive thread quit now ./n"); return;}int main(void){ struct parameters myPara; memset((void *)&myPara,0,sizeof(struct parameters));#ifdef PRIVATEIPC myPara.mqid=IPC_PRIVATE;#else myPara.mqid=ftok(MSGQUEUE_NAME,MSGQUEUE_ID);#endif myPara.oflag=IPC_CREAT; pthread_t pids; pthread_t pidr; pthread_create(&pids,NULL,(void *)msgSendThread,&myPara); pthread_create(&pidr,NULL,(void *)msgReceiveThread,&myPara); pthread_join(pidr,NULL); //printf("/tnow is here!/n"); pthread_join(pids,NULL); printf("main thread quit now./n"); return 0;}
sysvsem.c
#include <sys/ipc.h>#include <sys/sem.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <errno.h>#define SEM_NAME "/tmp/testllsem"#define SEM_ID 0#define BUFFERSIZE 64#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)/* union semun is defined by including <sys/sem.h> */#else/* according to X/OPEN we have to define it ourselves */union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ /* Linux specific part: */ struct seminfo *__buf; /* buffer for IPC_INFO */};#endifstruct ThreadPara{ key_t kid; int semid; unsigned int readerIndex; unsigned int writerIndex; char buffer[BUFFERSIZE];};void writerThread(void * data){ unsigned int counter=0; struct ThreadPara * myPa=(struct ThreadPara *)data; struct sembuf semops; semops.sem_flg=SEM_UNDO; for(;counter<10;counter++) { semops.sem_num=myPa->writerIndex; semops.sem_op=-1; //semops.sem_flg=SEM_UNDO; semop(myPa->semid,&semops,1); sprintf(myPa->buffer,"this is the #%d message",counter); semops.sem_num=myPa->readerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); //sleep(1); } semops.sem_num=myPa->writerIndex; semops.sem_op=-1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); memset(myPa->buffer,0,BUFFERSIZE); sprintf(myPa->buffer,"quitnow"); semops.sem_num=myPa->readerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); printf("now send thread quit./n"); return;}void readerThread(void * data){ struct ThreadPara * myPa=(struct ThreadPara *)data; struct sembuf semops; semops.sem_flg=SEM_UNDO; for(;;) { semops.sem_num=myPa->readerIndex; semops.sem_op=-1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); if(strncmp(myPa->buffer,"quitnow",7) == 0) { break; } printf("/tYes,i got buffer:%s./n",myPa->buffer); semops.sem_num=myPa->writerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); } printf("now receive thread quit./n"); return;}int main(void){ struct ThreadPara myPara; int oFlag; //mode_t oMode; union semun arg; memset(&myPara,0,sizeof(struct ThreadPara)); oFlag=IPC_CREAT|IPC_EXCL; //oMode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;#ifdef PRIVATEIPC myPara.kid=IPC_PRIVATE;#else myPara.kid=ftok(SEM_NAME,SEM_ID);#endif myPara.semid=semget(myPara.kid,2,oFlag); myPara.readerIndex=0; myPara.writerIndex=1; arg.val=0; semctl(myPara.semid,myPara.readerIndex,SETVAL,arg); arg.val=1; semctl(myPara.semid,myPara.writerIndex,SETVAL,arg); if(myPara.semid < 0) { if(errno == EEXIST) { printf("get sem err!/n"); } } pthread_t pidr; pthread_t pidw; pthread_create(&pidr,NULL,(void *)readerThread,&myPara); pthread_create(&pidw,NULL,(void *)writerThread,&myPara); pthread_join(pidr,NULL); pthread_join(pidw,NULL); semctl(myPara.semid,0,IPC_RMID); printf("now main thread quit./n"); return 0;}
sysvshm.c
#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <errno.h>#define SEM_NAME "/tmp/testllsem"#define SEM_ID 0#define SHM_NAME "/tmp/testllshm"#define SHM_ID 0#define SHMSIZE 64#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)/* union semun is defined by including <sys/sem.h> */#else/* according to X/OPEN we have to define it ourselves */union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ /* Linux specific part: */ struct seminfo *__buf; /* buffer for IPC_INFO */};#endifstruct ThreadPara{ key_t ksemid; key_t kshmid; int semid; int shmid; unsigned int readerIndex; unsigned int writerIndex; int shmsize;};void writerThread(void * data){ unsigned int counter=0; struct ThreadPara * myPa=(struct ThreadPara *)data; void * buffer; struct sembuf semops; semops.sem_flg=SEM_UNDO; buffer=shmat(myPa->shmid,NULL,0); for(;counter<10;counter++) { semops.sem_num=myPa->writerIndex; semops.sem_op=-1; //semops.sem_flg=SEM_UNDO; semop(myPa->semid,&semops,1); sprintf(buffer,"this is the #%d message",counter); semops.sem_num=myPa->readerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); //sleep(1); } semops.sem_num=myPa->writerIndex; semops.sem_op=-1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); memset(buffer,0,myPa->shmsize); sprintf(buffer,"quitnow"); semops.sem_num=myPa->readerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); shmdt(buffer); printf("now send thread quit./n"); return;}void readerThread(void * data){ struct ThreadPara * myPa=(struct ThreadPara *)data; void * buffer; struct sembuf semops; semops.sem_flg=SEM_UNDO; buffer=shmat(myPa->shmid,NULL,SHM_RDONLY); for(;;) { semops.sem_num=myPa->readerIndex; semops.sem_op=-1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); if(strncmp(buffer,"quitnow",7) == 0) { break; } printf("/tYes,i got buffer:%s./tthis is shm realization./n",(char *)buffer); semops.sem_num=myPa->writerIndex; semops.sem_op=1; //semops.sem_flg=0; semop(myPa->semid,&semops,1); } shmdt(buffer); printf("now receive thread quit./n"); return;}int main(void){ struct ThreadPara myPara; int oFlag; //mode_t oMode; union semun arg; memset(&myPara,0,sizeof(struct ThreadPara)); oFlag=IPC_CREAT|IPC_EXCL; //oMode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;#ifdef PRIVATEIPC myPara.ksemid=IPC_PRIVATE; myPara.kshmid=IPC_PRIVATE;#else myPara.ksemid=ftok(SEM_NAME,SEM_ID); myPara.kshmid=ftok(SHM_NAME,SHM_ID);#endif myPara.shmsize=SHMSIZE; myPara.semid=semget(myPara.ksemid,2,oFlag); if(myPara.semid < 0) { if(errno == EEXIST) { printf("get sem err!/n"); } } myPara.shmid=shmget(myPara.kshmid,myPara.shmsize,oFlag); if(myPara.shmid < 0) { if(errno == EEXIST) { printf("get shm err!/n"); } } myPara.readerIndex=0; myPara.writerIndex=1; arg.val=0; semctl(myPara.semid,myPara.readerIndex,SETVAL,arg); arg.val=1; semctl(myPara.semid,myPara.writerIndex,SETVAL,arg); pthread_t pidr; pthread_t pidw; pthread_create(&pidr,NULL,(void *)readerThread,&myPara); pthread_create(&pidw,NULL,(void *)writerThread,&myPara); pthread_join(pidr,NULL); pthread_join(pidw,NULL); semctl(myPara.semid,0,IPC_RMID); shmctl(myPara.shmid,IPC_RMID,NULL); printf("main thread quit now./n"); return 0;}
posixsem.c
#include <stdio.h>#include <stdlib.h>#include <semaphore.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/ipc.h>#include <fcntl.h>#include <errno.h>#define SEM_WRITER "/testllposixsemw"#define SEM_READER "/testllposixsemr"#define BUFFERSIZE 64struct ThreadPara{ sem_t * reader; sem_t * writer; char buffer[BUFFERSIZE];};void writerThread(void * data){ unsigned int counter=0; struct ThreadPara * myPa=(struct ThreadPara *)data; for(;counter<10;counter++) { sem_wait(myPa->writer); sprintf(myPa->buffer,"writer:this is the POSIX_SEM #%d message",counter); sem_post(myPa->reader); //sleep(1); } sem_wait(myPa->writer); memset(myPa->buffer,0,BUFFERSIZE); sprintf(myPa->buffer,"quitnow"); sem_post(myPa->reader); printf("now send thread quit./n"); return;}void readerThread(void * data){ struct ThreadPara * myPa=(struct ThreadPara *)data; for(;;) { sem_wait(myPa->reader); if(strncmp(myPa->buffer,"quitnow",7) == 0) { break; } printf("/treader:Yes,i got buffer:%s./n",myPa->buffer); sem_post(myPa->writer); //sleep(3); } printf("now receive thread quit./n"); return;}int main(void){ struct ThreadPara myPara; int oFlag; mode_t oMode; memset(&myPara,0,sizeof(struct ThreadPara)); //oFlag=O_CREAT|O_EXCL; oFlag=O_CREAT; oMode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; myPara.reader=sem_open(SEM_READER,oFlag,oMode,0); if(myPara.reader <= 0) { printf("failed to open sem reader/n"); switch(errno) { case EACCES: printf("EACCES------------/n"); break; case EEXIST: printf("EEXIST------------/n"); break; case EINTR: printf("EINTR------------/n"); break; case EINVAL: printf("EINVAL------------/n"); break; case ENAMETOOLONG: printf("ENAMETOOLONG------------/n"); case ENOENT: printf("ENOENT------------/n"); break; case ENOMEM: printf("ENOMEM------------/n"); break; case ENOSPC: printf("ENOSPC------------/n"); break; case EFAULT: printf("EFAULT------------/n"); break; case EMFILE: printf("EMFILE------------/n"); break; case ENFILE: printf("ENFILE------------/n"); break; default: break; } return -1; } myPara.writer=sem_open(SEM_WRITER,oFlag,oMode,1); if(myPara.writer <= 0) { switch(errno) { case EACCES: printf("EACCES------------/n"); break; case EEXIST: printf("EEXIST------------/n"); break; case EINTR: printf("EINTR------------/n"); break; case EINVAL: printf("EINVAL------------/n"); break; case ENAMETOOLONG: printf("ENAMETOOLONG------------/n"); case ENOENT: printf("ENOENT------------/n"); break; case ENOMEM: printf("ENOMEM------------/n"); break; case ENOSPC: printf("ENOSPC------------/n"); break; case EFAULT: printf("EFAULT------------/n"); break; case EMFILE: printf("EMFILE------------/n"); break; case ENFILE: printf("ENFILE------------/n"); break; default: break; } printf("failed to open sem writer/n"); } pthread_t pidr; pthread_t pidw; pthread_create(&pidr,NULL,(void *)readerThread,&myPara); pthread_create(&pidw,NULL,(void *)writerThread,&myPara); pthread_join(pidr,NULL); pthread_join(pidw,NULL); sem_close(myPara.reader); sem_close(myPara.writer); sem_unlink(SEM_READER); sem_unlink(SEM_WRITER); printf("now main thread quit./n"); return 0;}
外加一个简陋的Makefile。
CFLAGS=-O9 -Wall -g -D__POSIX_SOURCECINCLUDES=CLIBS=-lpthread -lrtPOSIXQUEUELIB=-lmqueueCC=gccall:tm one two tcrc pq vq psem vsem vshm pshmpshm:posixshm.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o pshm posixshm.c vshm:sysvshm.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o vshm sysvshm.c psem:posixsem.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o psem posixsem.c vsem:sysvsem.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o vsem sysvsem.cvq:sysvqueue.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o vq sysvqueue.cpq:posixqueue.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) $(POSIXQUEUELIB) -o pq posixqueue.ctcrc:testcrc.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o tcrc testcrc.ctm:testmain.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o tm testmain.cone:one.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o one one.ctwo:two.c $(CC) $(CFLAGS) $(CINCLUDES) $(CLIBS) -o two two.cclean: rm -f vshm rm -f pshm rm -f vsem rm -f psem rm -f pq rm -f vq rm -f tcrc rm -f one rm -f two rm -f tm rm -f a.out
留此备忘