现在的位置: 首页 > 综合 > 正文

Posex信号量 实现进程间的同步(生产者&消费者)

2018年09月21日 ⁄ 综合 ⁄ 共 1793字 ⁄ 字号 评论关闭

一 Posex信号量sem

#include <semaphore.h>

sem_t 信号量的类型

int sem_init(sem_t *sem, int pshared, unsigned int value);
  1)pshared==0 用于同一多线程的同步;
  2)若pshared>0 用于多个进程间的同步,此时sem必须放在共享内存中。
  最后,value 是信号量的初值。

int sem_wait(sem_t *sem);
    测试所指定信号量的值,它的操作是原子的。
    sem<=0 将sem-1 进程\线程进入休眠等待状态,即被唤起返回
    sem>0  将sem-1 进程获取到1个资源返回

int sem_post(sem_t *sem);
    把指定的信号量sem的值加1;
    呼醒正在等待该信号量的任意线程(如果存在,即sem<=0)。

共享内存api
建立一块共享空间:
int shmget(key,size,flag)
以key作为标志,设置一块size大小的共享存储,而flag是此存储的访问权限;
进程对共享存储的映射:
void* shmat(shmid,void *add,flag)
shmid为shmget建立的共享存储区块标志,add指定进程使用哪个地址映射到共享存储的地址(设置为0表示由内核帮助设置)。
返回一个进程用于映射共享存储的首地址,通过该地址即可完成对共享存储的操作。

二 sem实现进程的p-v操作

    sem实现多个线程的互斥,只需在进程空间定义好sem_t变量即可,因为各个线程是共享该sem_t变量。同理,如果sem要实现进程间的互斥,这个sem_t的变量就要在共享存储中定义,因为,两个进程对sem_t的操作必须是同一个地址空间的变量,才能实现信息同步,从而达到互斥的目的。而进程间的数据共享,用共享存储即可。

三 代码实现生产者-消费者

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/shm.h>

int main()
{
    int shmid;
    sem_t *sem_product,*sem_consume;//分别为生产信号量和消费信号量

    //在共享存储中创建两sem_t的信号量
    if(shmid = shmget(IPC_PRIVATE,sizeof(sem_t)*2,0600))
        perror("shmget error:");
    if((sem_product = shmat(shmid,0,0600)))
        perror("shmat error:");
    sem_consume = &sem_product[1];

    //设置这两个信号量的初始化
    if(sem_init(sem_consume,1,0))
        perror("sem_init error:");
    if(sem_init(sem_product,1,0))
        perror("sem_init error:");

    pid_t cpid;
    cpid = fork();
    printf("@fter fork\n");
    if(cpid == -1){
        perror("fork error");
        exit(0);
    }
    if(cpid == 0)
    {
        printf("@child\n");
        while(1){
            sem_wait(sem_product);
            sleep(1);
            printf("pid:%d product...\n",getpid());
            sem_post(sem_consume);
        }
    }
    else{
        printf("@parent\n");
        while(1)
        {
            sem_post(sem_product);
            sem_wait(sem_consume);
            printf("pid:%d consume...\n",getpid());
        }
    }
}:

运行结果:

root@cloud2:~/slp/mylinuxcprogram# ./sem.out 
shmget error:: Success
shmat error:: Success
@fter fork
@parent
@fter fork
@child
pid:25957 product...
pid:25956 consume...
pid:25957 product...
pid:25956 consume...

...

抱歉!评论已关闭.