Unix网络编程源码解析_进程间通信IPC之(Posix)基于内存的信号量

 

 

#inlcude 


int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);

信号量是随内存区的持续性而存在的。

当参数pshared 为0时,表示一个进程中各个线程共享的内存区,进程终止,信号量随进程的内存消失而消亡;

当参数pshared 为1(非零时),表示基于内存的信号量在不同进程间共享的;

应用在单个生产-单个消费者的实例,同有名信号量效果一样,最主要就是信号量初始化和结束的函数调用发生了变化,然后就是在shared结构体中,有名信号量用的指针,基于内存的信号量使用的是普通变量,两者效果一样,都是传的地址空间;

Unix网络编程源码解析_进程间通信IPC之(Posix)基于内存的信号量_第1张图片

源码如下:

#include        "pxsem2.h"

#define NBUFF    10

int             nitems;                                 /* read-only by producer and consumer */
struct {        /* data shared by producer and consumer */
  int   buff[NBUFF];
  sem_t mutex, nempty, nstored;         /* semaphores, not pointers */
} shared;

void    *produce(void *), *consume(void *);

int
main(int argc, char **argv)
{
        pthread_t       tid_produce, tid_consume;

        if (argc != 2)
                err_quit("usage: prodcons2 <#items>");
        nitems = atoi(argv[1]);

                /* 4initialize three semaphores */
        Sem_init(&shared.mutex, 0, 1);
        Sem_init(&shared.nempty, 0, NBUFF);
        Sem_init(&shared.nstored, 0, 0);

        Set_concurrency(2);
        Pthread_create(&tid_produce, NULL, produce, NULL);
        Pthread_create(&tid_consume, NULL, consume, NULL);

        Pthread_join(tid_produce, NULL);
        Pthread_join(tid_consume, NULL);

        Sem_destroy(&shared.mutex);
        Sem_destroy(&shared.nempty);
        Sem_destroy(&shared.nstored);
        exit(0);
}
void *
produce(void *arg)
{
        int             i;

        for (i = 0; i < nitems; i++) {
                Sem_wait(&shared.nempty);       /* wait for at least 1 empty slot */
                Sem_wait(&shared.mutex);
                shared.buff[i % NBUFF] = i;     /* store i into circular buffer */
                printf("producter buff[%d] = %d\n", (i%NBUFF), shared.buff[i % NBUFF]);
                Sem_post(&shared.mutex);
                Sem_post(&shared.nstored);      /* 1 more stored item */
        }
        return(NULL);
}

void *
consume(void *arg)
{
        int             i;

        for (i = 0; i < nitems; i++) {
                Sem_wait(&shared.nstored);              /* wait for at least 1 stored item */
                Sem_wait(&shared.mutex);
                if (shared.buff[i % NBUFF] != i)
                        printf("buff[%d] = %d\n", i, shared.buff[i % NBUFF]);
                printf("comsumer buff[%d] = %d\n", (i%NBUFF), shared.buff[i % NBUFF]);
                Sem_post(&shared.mutex);
                Sem_post(&shared.nempty);               /* 1 more empty slot */
        }
        return(NULL);
}
                                           

执行效果如下:

Unix网络编程源码解析_进程间通信IPC之(Posix)基于内存的信号量_第2张图片

第二部分,多个生产者,单个消费者问题;

 

源码

/* include main */
#include        "pxsem3.h"

#define NBUFF            10
#define MAXNTHREADS     100

int             nitems, nproducers;             /* read-only by producer and consumer */

struct {        /* data shared by producers and consumer */
  int   buff[NBUFF];
  int   nput;
  int   nputval;
  sem_t mutex, nempty, nstored;         /* semaphores, not pointers */
} shared;

void    *produce(void *), *consume(void *);

int
main(int argc, char **argv)
{
        int             i, count[MAXNTHREADS];
        pthread_t       tid_produce[MAXNTHREADS], tid_consume;

        if (argc != 3)
                err_quit("usage: prodcons3 <#items> <#producers>");
        nitems = atoi(argv[1]);
        nproducers = min(atoi(argv[2]), MAXNTHREADS);

                /* 4initialize three semaphores */
        Sem_init(&shared.mutex, 0, 1);
        Sem_init(&shared.nempty, 0, NBUFF);
        Sem_init(&shared.nstored, 0, 0);

                /* 4create all producers and one consumer */
        Set_concurrency(nproducers + 1);
        for (i = 0; i < nproducers; i++) {
                count[i] = 0;
                Pthread_create(&tid_produce[i], NULL, produce, &count[i]);
        }
        Pthread_create(&tid_consume, NULL, consume, NULL);

                /* 4wait for all producers and the consumer */
        for (i = 0; i < nproducers; i++) {
                 Pthread_join(tid_produce[i], NULL);
                printf("count[%d] = %d\n", i, count[i]);
        }
        Pthread_join(tid_consume, NULL);

        Sem_destroy(&shared.mutex);
        Sem_destroy(&shared.nempty);
        Sem_destroy(&shared.nstored);
        exit(0);
}
/* end main */

/* include produce */
void *
produce(void *arg)
{
        for ( ; ; ) {
                Sem_wait(&shared.nempty);       /* wait for at least 1 empty slot */
                Sem_wait(&shared.mutex);

                if (shared.nput >= nitems) {
                        Sem_post(&shared.nempty);
                        Sem_post(&shared.mutex);
                        return(NULL);                   /* all done */
                }

                shared.buff[shared.nput % NBUFF] = shared.nputval;
                shared.nput++;
                shared.nputval++;

                Sem_post(&shared.mutex);
                Sem_post(&shared.nstored);      /* 1 more stored item */
                *((int *) arg) += 1;
        }
}
/* end produce */

/* include consume */
void *
consume(void *arg)
{
        int             i;

        for (i = 0; i < nitems; i++) {
                Sem_wait(&shared.nstored);              /* wait for at least 1 stored item */
                Sem_wait(&shared.mutex);

                if (shared.buff[i % NBUFF] != i)
                        printf("error: buff[%d] = %d\n", i, shared.buff[i % NBUFF]);

                Sem_post(&shared.mutex);
                Sem_post(&shared.nempty);               /* 1 more empty slot */
        }
        return(NULL);
}
/* end consume */

线程相关的调用,在互斥锁部分已经介绍的很详细了,与以上单个生产——单个消费者实例相比,最主要的变化就是生产者的执行函数多了以下调用;

if (shared.nput >= nitems) {
        Sem_post(&shared.nempty);
        Sem_post(&shared.mutex);
        return(NULL);                   /* all done */
                }

因为当生产计划完成了,但是多个生产者线程都还没停止,但总有第一个生产者线程先获取最后一个shared.nempty资源,获取后shared.nempty的值就会减1变为0,那么这个线程是能正常结束,但是其他的生产者线程永远阻塞等待shared.nempty;所以有了以上的函数调用,能帮助其他线程都正常执行结束;

 

 

你可能感兴趣的:(linux)