IPC通信_信号量

信号量是一个计数器,用于为多个进程提供对共享数据的访问。

函数1

#include <sys/sem.h>
int semget(key_t key, int nsems, int flag);

该函数转换键值获取信号量ID, key键值的获取还是通过ftok函数。

返回值  :成功返回信号量ID, 失败返回-1

参数key  :键值(key)

参数nsems:初始信号量集合中的数组个数,如果是新建的必须指定该值,如果引用已有信号量,则置为0

参数flag   :设置的权限,可参考消息队列。

函数2

#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, .../*union semun arg*/);

该函数对信号量执行多种操作。其中第四个参数arg可选,是否使用取决于所请求的命令。

  union semun

  {

    int val;             

    struct semid_ds *buf;

    unsigned short* array;

  }

参数semid :信号量ID

参数semnum:指定信号量集合中哪个成员,从0nsems-1

参数cmd    :见下表

cmd参数

释意

IPC_STAT

参考消息队列

IPC_SET

参考消息队列,第四个参数取联合中的arg.buf

IPC_RMID

参考消息队列

GETVAL

返回成员semnumsemval

SETVAL

设置成员semnumsemval值,该值由arg.val指定

GETPID

返回成员semnumsempid

GETNCNT

返回成员semnumsemncnt

GETZCNT

返回成员semnumsemzcnt

GETALL

取该集合中所有的信号量值。这些值存储在arg.array指向的数组中

SETALL

将该集合中所有的信号量值设置成arg.array指向的数值中的值

返回值: 除了GETALL以外的所有get命令,semctl函数都返回相应值。其他命令成功0,失败返回-1

 函数3

#include <sys/sem.h>
int semop(int semid, struct sembuf semoparray[], size_t nops);

返回值:成功返回0,失败返回-1

参数semid:信号量ID

参数semoparray:一个指针,指向有sembuf结构表示的信号量操作数组

struct sembuf

{

unsigned short sem_num; //操作第几个信号量,0~nsems-1

short sem_op; //信号量要加减的数,可以是正数、负数、0

short sem_flg; //标志位IPC_NOWAIT, SEM_UNDO

}

参数nops:规定该数组中操作的数量

举例:

两个线程,一个线程通过信号量控制另一个信息打印

sem_1.cpp

 

#include <unistd.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <sys/sem.h>  
  
union semun  
{  
    int val;  
    struct semid_ds *buf;  
    unsigned short *arry;  
};  
  
int set_semvalue(int sem_id, int count)  
{//用于初始化信号量,在使用信号量前必须这样做  
    union semun sem_union;  
    sem_union.val = count;  
    if(semctl(sem_id, 0, SETVAL, sem_union) == -1)  
    {
        printf("set_semvalue failed\n");
        return -1;
    }        
    return 0;  
}  
  
void del_semvalue(int sem_id)  
{//删除信号量  
    union semun sem_union;  
    if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) 
    {
        printf("del_semvalue failed\n");
    }        
}  
  
int semaphore_p(int sem_id)  
{//对信号量做减1操作,即等待P(sv)  
    struct sembuf sem_b;  
    sem_b.sem_num = 0;  
    sem_b.sem_op = -1;//P()  
    sem_b.sem_flg = SEM_UNDO;  
    if(semop(sem_id, &sem_b, 1) == -1)  
    {  
        printf("semaphore_p failed\n");
        return -1;  
    }  
    return 0;  
}  
int semaphore_v(int sem_id)  
{//这是一个释放操作,它使信号量变为可用,即发送信号V(sv)  
    struct sembuf sem_b;  
    sem_b.sem_num = 0;  
    sem_b.sem_op = 1;//V()  
    sem_b.sem_flg = SEM_UNDO;  
    if(semop(sem_id, &sem_b, 1) == -1)  
    {  
        printf("semaphore_v failed\n");
        return -1;  
    }  
    return 0; 
} 
  
int main(int argc, char *argv[])  
{  
    key_t key = ftok("/tmp/",2);
    //创建信号量  
    int sem_id = semget(key, 1, 0666 | IPC_CREAT);  
    
    set_semvalue(sem_id, 0);
 
    for(int i = 0; i < 10; ++i)  
    {  
        semaphore_p(sem_id);
        printf("sem1 print\n");
    }  
  
    printf("\n%d - finished\n", getpid());  
  
    del_semvalue(sem_id);  
    return 0;  
}  

 

sem_2.cpp

#include <unistd.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <sys/sem.h>  
  
union semun  
{  
    int val;  
    struct semid_ds *buf;  
    unsigned short *arry;  
};  
  
int set_semvalue(int sem_id, int count)  
{//用于初始化信号量,在使用信号量前必须这样做  
    union semun sem_union;  
    sem_union.val = count;  
    if(semctl(sem_id, 0, SETVAL, sem_union) == -1)  
    {
        printf("set_semvalue failed\n");
        return -1;
    }        
    return 0;  
}  
  
void del_semvalue(int sem_id)  
{//删除信号量  
    union semun sem_union;  
    if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) 
    {
        printf("del_semvalue failed\n");
    }        
}  
  
int semaphore_p(int sem_id)  
{//对信号量做减1操作,即等待P(sv)  
    struct sembuf sem_b;  
    sem_b.sem_num = 0;  
    sem_b.sem_op = -1;//P()  
    sem_b.sem_flg = SEM_UNDO;  
    if(semop(sem_id, &sem_b, 1) == -1)  
    {  
        printf("semaphore_p failed\n");
        return -1;  
    }  
    return 0;  
}  
int semaphore_v(int sem_id)  
{//这是一个释放操作,它使信号量变为可用,即发送信号V(sv)  
    struct sembuf sem_b;  
    sem_b.sem_num = 0;  
    sem_b.sem_op = 1;//V()  
    sem_b.sem_flg = SEM_UNDO;  
    if(semop(sem_id, &sem_b, 1) == -1)  
    {  
        printf("semaphore_v failed\n");
        return -1;  
    }  
    return 0; 
} 
  
int main(int argc, char *argv[])  
{  
    key_t key = ftok("/tmp/",2);
    //创建信号量  
    int sem_id = semget(key, 1, 0666 | IPC_CREAT);  
    
    //set_semvalue(sem_id, 0);
 
    for(int i = 0; i < 10; ++i)  
    {  
        //semaphore_p(sem_id);
        printf("sem2 semaphore_v\n");
        semaphore_v(sem_id);
        sleep(1);
    }  
  
    printf("\n%d - finished\n", getpid());  
  
    //del_semvalue(sem_id);  
    return 0;  
}  
  

 

posted @ 2020-02-04 21:11  ho966  阅读(185)  评论(0编辑  收藏  举报