semget()
     可以使用系统调用semget() 创建一个新的信号量集,或者存取一个已经存在的信号量集 :

系统调用:semget();
原型:intsemget(key_t key,int nsems,int semflg);
返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1:errno=EACCESS(没有权限)
EEXIST(信号量集已经存在,无法创建)
EIDRM(信号量集已经删除)
ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
ENOMEM(没有足够的内存创建新的信号量集)
ENOSPC(超出限制)
    系统调用semget()的第一个参数是关键字值(一般是由系统调用ftok()返回的)。系统内核将此值和系统中存在的其他的信号量集的关键字值进行比较。打开和存取操作与参数semflg中的内容相关。IPC_CREAT如果信号量集在系统内核中不存在,则创建信号量集。IPC_EXCL当和 IPC_CREAT一同使用时,如果信号量集已经存在,则调用失败。如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识符,要么返回系统中已经存在的同样的关键字值的信号量的标识符。如果IPC_EXCL和IPC_CREAT一同使用,则要么返回新创建的信号量集的标识符,要么返回-1。IPC_EXCL单独使用没有意义。参数nsems指出了一个新的信号量集中应该创建的信号量的个数。信号量集中最多的信号量的个数是在linux/sem.h中定义的:
#defineSEMMSL32/*<=512maxnumofsemaphoresperid*/
下面是一个打开和创建信号量集的程序:
intopen_semaphore_set(key_t keyval,int numsems)
{
intsid;
if(!numsems)
return(-1);
if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1)
{
return(-1);
}
return(sid);
}
};
==============================================================

semop()
系统调用:semop();
调用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
返回值:0,如果成功。-1,如果失败:errno=E2BIG(nsops大于最大的ops数目)
EACCESS(权限不够)
EAGAIN(使用了IPC_NOWAIT,但操作不能继续进行)
EFAULT(sops指向的地址无效)
EIDRM(信号量集已经删除)
EINTR(当睡眠时接收到其他信号)
EINVAL(信号量集不存在,或者semid无效)
ENOMEM(使用了SEM_UNDO,但无足够的内存创建所需的数据结构)
ERANGE(信号量值超出范围)

第一个参数是关键字值。第二个参数是指向将要操作的数组的指针。第三个参数是数组中的操作的个数。参数sops指向由sembuf组成的数组。此数组是在linux/sem.h中定义的:
/*semop systemcall takes an array of these*/
structsembuf{
ushortsem_num;/*semaphore index in array*/
shortsem_op;/*semaphore operation*/
shortsem_flg;/*operation flags*/
sem_num将要处理的信号量的个数。
sem_op要执行的操作。
sem_flg操作标志。
如果sem_op是负数,那么信号量将减去它的值。这和信号量控制的资源有关。如果没有使用IPC_NOWAIT,那么调用进程将进入睡眠状态,直到信号量控制的资源可以使用为止。如果sem_op是正数,则信号量加上它的值。这也就是进程释放信号量控制的资源。最后,如果sem_op是0,那么调用进程将调用sleep(),直到信号量的值为0。这在一个进程等待完全空闲的资源时使用。
===============================================================

semctl()
系统调用:semctl();
原型:int semctl(int semid,int semnum,int cmd,union semunarg);
返回值:如果成功,则为一个正数。
如果失败,则为-1:errno=EACCESS(权限不够)
EFAULT(arg指向的地址无效)
EIDRM(信号量集已经删除)
EINVAL(信号量集不存在,或者semid无效)
EPERM(EUID没有cmd的权利)
ERANGE(信号量值超出范围)

系统调用semctl用来执行在信号量集上的控制操作。这和在消息队列中的系统调用msgctl是十分相似的。但这两个系统调用的参数略有不同。因为信号量一般是作为一个信号量集使用的,而不是一个单独的信号量。所以在信号量集的操作中,不但要知道IPC关键字值,也要知道信号量集中的具体的信号量。这两个系统调用都使用了参数cmd,它用来指出要操作的具体命令。两个系统调用中的最后一个参数也不一样。在系统调用msgctl中,最后一个参数是指向内核中使用的数据结构的指针。我们使用此数据结构来取得有关消息队列的一些信息,以及设置或者改变队列的存取权限和使用者。但在信号量中支持额外的可选的命令,这样就要求有一个更为复杂的数据结构。
系统调用semctl()的第一个参数是关键字值。第二个参数是信号量数目。
参数cmd中可以使用的命令如下:
    ·IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
    ·IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
    ·IPC_RMID将信号量集从内存中删除。
    ·GETALL用于读取信号量集中的所有信号量的值。
    ·GETNCNT返回正在等待资源的进程数目。
    ·GETPID返回最后一个执行semop操作的进程的PID。
    ·GETVAL返回信号量集中的一个单个的信号量的值。
    ·GETZCNT返回这在等待完全空闲的资源的进程数目。
    ·SETALL设置信号量集中的所有的信号量的值。
    ·SETVAL设置信号量集中的一个单独的信号量的值。
参数arg代表一个semun的实例。semun是在linux/sem.h中定义的:
/*arg for semctl systemcalls.*/
unionsemun{
intval;/*value for SETVAL*/
structsemid_ds*buf;/*buffer for IPC_STAT&IPC_SET*/
ushort*array;/*array for GETALL&SETALL*/
structseminfo*__buf;/*buffer for IPC_INFO*/
void*__pad;
val当执行SETVAL命令时使用。buf在IPC_STAT/IPC_SET命令中使用。代表了内核中使用的信号量的数据结构。array在使用GETALL/SETALL命令时使用的指针。
    下面的程序返回信号量的值。当使用GETVAL命令时,调用中的最后一个参数被忽略:
intget_sem_val(intsid,intsemnum)
{
return(semctl(sid,semnum,GETVAL,0));
}
下面是一个实际应用的例子:
#defineMAX_PRINTERS5
printer_usage()
{
int x;
for(x=0;x<max_printers;x++)
printf("Printer%d:%d\n\r",x,get_sem_val(sid,x));
}
下面的程序可以用来初始化一个新的信号量值:
void init_semaphore(int sid,int semnum,int initval)
{
union semunsemopts;
semopts.val=initval;
semctl(sid,semnum,SETVAL,semopts);
}
注意系统调用semctl中的最后一个参数是一个联合类型的副本,而不是一个指向联合类型的指针。

#include 
#include 
#include 
#include 
#include 
#include

#define KEY1 1492
#define KEY2 1493
#define KEY3 1494
#define IFLAGS (IPC_CREAT|IPC_EXCL)
#define N 1

#define SEMKEY1 (key_t)0x2000
#define SEMKEY2 (key_t)0x2001
#define SEMKEY3 (key_t)0x2002

union semun{
    int val;
    struct semid_ds *buf;
    unsigned short * ary;
};

int ctr_sem(key_t key,int inival)
{
    union semun argument;
    int id;
    //if ((id=semget(key,1,IPC_CREAT))<0)
    if ((id=semget(key,1,IPC_CREAT))<0)
    {
        printf("semget error\n");
    } 
    argument.val=inival;
    if (semctl(id,0,SETVAL,argument)<0)
    {
        printf("semctrl error\n");
    }
    return id;
}

int sem_init(key_t key, int inival)
{
  int semid; 
  union semun arg;
  semid=semget(key,1,0660|IFLAGS);
  arg.val=inival;
  semctl(semid, 0, SETVAL, arg);
  return semid;
}

void P(int semid)
{
    struct sembuf sb; 
    sb.sem_num=0;
    sb.sem_op=-1;
    sb.sem_flg=0;
    semop(semid,&sb,1);
}

void V(int semid)
{
    struct sembuf sb; 
    sb.sem_num=0;
    sb.sem_op=1;
    sb.sem_flg=0;
    semop(semid,&sb,1); 
}

int productItem()
{
    static int i=1;
    printf("Produce a product %d\n",i);
    return i++;
}

void consumeItem(int item)
{
    printf("Consume a product %d\n",item);
}

int main(void)
{
    int nshm=shmget(ftok("/root",'a'),1024,IPC_CREAT);
    int *buffer=(int *)shmat(nshm,0,0);

//     int products=ctr_sem(KEY1/*ftok("/home/jingenl",'p')*/,0);
//     int space=ctr_sem(KEY2/*ftok("/home/jingenl",'s')*/,N);
//     int mutex=ctr_sem(KEY3/*ftok("/home/jingenl",'m')*/,1);

int products=sem_init(SEMKEY1,0);
    int space=sem_init(SEMKEY2,N);
    int mutex=sem_init(SEMKEY3,1);

int i=0,j=0;

if(fork()==0)
    {
          int item;
          while(1)
          {
                P(space);
                P(mutex);
                item=productItem();
                *(buffer + sizeof(int)*i)=item;
                i=(i+1)%N;
                V(mutex);
                V(products);
          }
    }
    else
    {
          int item;
          while(1)
          {
                P(products);
                P(mutex);
                item=*(buffer + sizeof(int)*j);
                j=(j+1)%N;
                consumeItem(item);
                V(mutex);
                V(space);
          }
                    
    }
    return 0;
}

信号量函数 semget() semop() semctl()相关推荐

  1. SystemV 信号量(一) —— SystemV信号量的相关操作函数(semget / semop /semctl)

    SystemV IPC 方案的相关内容都是通过 "房间密码"来创建房间,获取到房间的ID,后面其他进程也可以根据这个房间密码来拿到同一个房间的ID.这是理解下面这些操作函数的关键. ...

  2. C语言sem Take函数,信号量函数sem.c

    信号量函数sem.c 来源:华强电子网 作者:华仔 浏览:148 时间:2016-08-10 14:18 标签: 摘要: ;;; MantisOS中下信号量函数sem.c,主要调用了Linux底层的A ...

  3. 信号量 Linux函数 semget();semctl();semop();

    Linux进程通信之信号量 信号量(semaphore)是变量,是一种特殊的变量.它紧取正值.对信息号量的操作只有2中: 等待(wait)和发送信号(signal). 信号量比较难理解.下面我们一个个 ...

  4. 系统编程04-消息队列(ftok、msgget、msgsnd、msgrcv、msgctl、shmget、shmat、shmdt、shmctl、semget、semctl、semop)

    目录 一.linuxIPC对象 (Inter Process Communicate) 1.什么是IPC对象 1)想要操作文件(设备文件/dev): 2)想要操作消息队列: 2.查看系统中所有的IPC ...

  5. 十六:CreateSemaphore创建信号量,ReleaseSemaphore增加信号量 函数

    在开发软件的过程中,多线程的程序往往需要实现相互通讯,比如几个线程添加一个消息到队列里,而另一个线程在睡眠时,就需要唤醒那个线程来处理事情.在这其中,就需要使用到信号量来进行同步.CreateSema ...

  6. Linux 3.进程间通信(shmget shmat shmdt shmctl 共享内存、signal signaction sigqueue 信号、semget semctl semop 信号量)

    Linux 3.进程间通信(IPC) 共享内存 共享内存的接口指令 shmget 创建获取获取共享内存 shmat 映射:连接共享内存到当前进程的地址空间 shmdt 断开与共享内存的连接 shmct ...

  7. 专题 13 IPC之信号量

    1.概述 信号量是一种计数器,用来控制对多个进程共享的资源所进行的访问.它们常被用做一个锁机制. 2.相关数据结构与函数 信号量数据结构: structsemun { intval;//当执行SETV ...

  8. linux系统调用函数---12

    Linux应用编程学习笔记                                 周学伟 一.系统调用文件编程   1.文件打开函数 /*************************** ...

  9. linux 编程函数原型与用法

    函数原型以及部分实例应用 --------------------------------------------------------------------------------------- ...

最新文章

  1. schema类SpringMVC+Hibernate+Spring整合(二)
  2. Angular 2 Output
  3. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! test_vue_0613@1.0.0 dev: 错误的解决方法
  4. 2011年100佳精美的WordPress免费博客模板
  5. matlab和python哪个好学_python和matlab哪个难
  6. ^_^ 一看就忘不了的IE页面 ^_^
  7. 得到python默认的帮助文档
  8. 2022年后人工智能/深度学习八大应用方向
  9. 每个tabpage中都有一个dategridview_每个女人,都有一个礼服梦
  10. html访问java接口出现缓存_高可用架构设计(3) -电商商品详情页缓存背景及框架说明...
  11. 数据结构基础 后序遍历和中序遍历还原二叉树
  12. 尊重用户,提升产品欢迎度
  13. 图 邻接表 建立 深度遍历 广度遍历
  14. php end array_value,PHP常用处理数组函数
  15. DS博客大作业--树(李天明组)
  16. opencv摄像头拍摄视频并保存方法
  17. 全网首发:GB18030制定者站出来,$为什么要显示为¥,给大家解释一下
  18. 橙瓜发布2018网络小说风云榜年度榜,顶级大神作家的无声角逐
  19. 数学建模——模拟退火优化投影寻踪
  20. MySQL 日志的类型

热门文章

  1. Linux Shell函数返回值
  2. fatal error LNK1561: 必须定义入口点问题的我是这样解决的
  3. HDU - 7008 水题(打表)
  4. SDUT - Mountain Subsequences(dp)
  5. CodeForces - 1343F Restore the Permutation by Sorted Segments(思维)
  6. CodeForces - 1339D Edge Weight Assignment(思维)
  7. HYSBZ - 2342 双倍回文(回文自动机)
  8. 安川机器人焊枪切换设定方法_安川机器人参数更改方法
  9. 动态规划算法-02矿工挖矿问题
  10. 安装失败java.lang_linux安装jdk出现java/lang/NoClassDefFoundError: java/lang/Object错误的解决方案...