Linux程序设计笔记--IPC操作--semaphores

IPC操作就是通常说的进程间通信(interProcessCommunication,进程间通信)IPC操作有三种:信号量,共享内存,消息队列。

1.信号量。

信号量的作用是保证共享资源有效访问。

信号量有关函数:

int semget(key_tkey,int num_sems,int sem_flags);获取或者创建键值key对应的信号量,返回值信号量标识符。

key_t信号量键值,可以随意取。特殊键值IPC_PRIVATE,创建只能有本进程使用的信号量。

num_sems信号量的个数,一般取1

sem_flags信号量的访问权限,与open中的权限相似,与IPC_CREAT或操作,如果不存在创建信号量,如果存在忽略IPC_CREAT关键字,直接获取信号量标识符。

int semop(intsem_id,struct sembuf *sem_ops,size_t num_sem_ops); //信号量PV操作。

struct sembuf

{

short sem_num;//信号量的编号,工作方式不需要一组信号量,这个值为0

short sem_op; //对信号量PV操作时,加减的数值,可以为+1-1,或其他。

short sam_flg;//通常设置为SEM_UNDO。作用是:程序在没有释放信号量的情况下结束时,系统自动释放该信号量。

};

sem_id信号量标识符。sembuf信号量操作数值。num_sem_ops通常设置为1.

int semctl(intsem_id,int sem_num,int command,...); //对信号量的管理具体操作。

sem_id信号量标识符,sem_num信号量的标号。command采取的动作。如果有第四个参数,将会是一个unionsemun复合结构。只要包括以下成员:

union semun{

int val;

struct semid_ds*buf;

unsigned short*arry;

}

一般常用的command操作有两个:

SET_VAL:用来把信号量初始化为一个已知的值。这个值有unionsemun结构离得val值传递。

IPC_RMID:删除一个已经没人继续使用的信号量标识码。

semctl函数根据不同的command命令返回不同的值,SET_VAL,IPC_RMID操作成功返回0,失败返回-1


Semarphore


#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>


#include <sys/sem.h>


#include "semun.h"


union semun {

     int val; /* value for SETVAL */

     structsemid_ds *buf; /* buffer for IPC_STAT, IPC_SET */

     unsignedshort int *array; /* array for GETALL, SETALL */

     structseminfo *__buf; /* buffer for IPC_INFO */

};


static intset_semvalue(void);

static voiddel_semvalue(void);

static intsemaphore_p(void);

static intsemaphore_v(void);


static int sem_id;


int main(int argc,char *argv[])

{

     int i;

     int pause_time;

     char op_char ='O';


     srand((unsignedint)getpid());

     sem_id =semget((key_t)1234, 1, 0666 | IPC_CREAT);

     if (argc > 1){

         if(!set_semvalue()) {

             fprintf(stderr, "Failed to initialize semaphore\n");

             exit(EXIT_FAILURE);

          }

     op_char ='X';

     sleep(2);

     }


     for(i = 0; i <10; i++) {


     if(!semaphore_p()) exit(EXIT_FAILURE);

     printf("%c",op_char);fflush(stdout);

     pause_time =rand() % 3;

     sleep(pause_time);

     printf("%c",op_char);fflush(stdout);


     if(!semaphore_v()) exit(EXIT_FAILURE);

         pause_time =rand() % 2;

         sleep(pause_time);

     }


     printf("\n%d- finished\n", getpid());


     if (argc > 1){

        sleep(10);

        del_semvalue();

    }

    exit(EXIT_SUCCESS);

}


static intset_semvalue(void)

{

    union semunsem_union;


    sem_union.val =1;

    if(semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);

        return(1);

    }


static voiddel_semvalue(void)

{

    union semunsem_union;

    if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

    fprintf(stderr, "Failed to delete semaphore\n");

}


static intsemaphore_p(void)

{

    struct sembufsem_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) {

        fprintf(stderr, "semaphore_p failed\n");

        return(0);

    }

    return(1);

}


static intsemaphore_v(void)

{

    struct sembufsem_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) {

        fprintf(stderr, "semaphore_v failed\n");

        return(0);

    }

    return(1);

}


你可能感兴趣的:(Linux程序设计笔记--IPC操作--semaphores)