Linux IPC备忘

    技术2022-05-11  50

          大概在很久之前就一直关注的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 留此备忘 

    最新回复(0)