寒假学习 第25天 (linux 高级编程)

来源:互联网 发布:apache监控工具 编辑:程序博客网 时间:2024/04/27 16:30

寒假学习 第25天 (linux 高级编程) 笔记总结


一、信号量(进程同步)


模型

(1)创建或者得到信号量     semget

       int semget(key_t key, 

                         int nsems, //信号量数组的个数

                          int semflg); ////信号量的创建标记   创建:IPC_CREAT  IPC_EXCL(防止重复创建),打开:就是0

(2)初始化信号量中指定下标的值      semctl

             int semctl(int semid,

                              int semnum, 

                              int cmd,//操作 SETVAL   IPC_RMID  如果是IPC_RMID则semnu跟 ... 都无意义

                               ...);


           union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

(3)根据信号量阻塞或者解除阻塞     semop

           int semop(int semid,  //共享信号量的ID

                           struct sembuf *sops,  //描述对信号量的操作,操作可以是数组

                           unsigned nsops); //第二个参数的个数(操作个数) (如果是两个操作,两个操作都会执行)

           struct sembuf成员:

                unsigned short sem_num;  //下标
                short          sem_op;  //负数 够减函数返回不阻塞,不够减阻塞  / 正数 /  0 判定信号量是否 > 0 ,>0则阻塞直到信号量为0
                short          sem_flg; //建议为0

       控制坚持到搭配方式:

            +(解除阻塞)     -(阻塞)

            0(阻塞)            -(解除阻塞)

(4)删除信号量       semctl

          semctl(semid,0,IPC_RMID);

例子1:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/sem.h>int main(int argc, const char *argv[]){    key_t key;    int semid;    key=ftok(".",22);    if(key==-1) printf("ftok error:%m\n"),exit(-1);    semid=semget(key,1,IPC_CREAT|IPC_EXCL|0666);  //创建信号量    if(semid==-1) printf("semget error:%m\n") ,exit(-1);    return 0;}

这样ipcs -s就会看到新增加的信号量



例子2:(用上面程序创建的信号量)

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/sem.h>union semun {    int              val;    /* Value for SETVAL */    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */    unsigned short  *array;  /* Array for GETALL, SETALL */    struct seminfo  *__buf;  /* Buffer for IPC_INFO                                (Linux-specific) */};int main(int argc, const char *argv[]){    key_t key;    int semid;    key=ftok(".",22);    if(key==-1) printf("ftok error:%m\n"),exit(-1);    //semid=semget(key,1,IPC_CREAT|IPC_EXCL|0666);    //if(semid==-1) printf("semget error:%m\n") ,exit(-1);    semid=semget(key,1,0);    //得到信号量    if(semid==-1) printf("semget error:%m\n") ,exit(-1);    printf("semid:%d\n",semid);    union semun v;     v.val=2; //初始值为2        int r;    r=semctl(semid,0,SETVAL,v);   //设置信号量的值    if(r==-1) printf("semctl error:%m\n"),exit(-1);    //对信号量进行阻塞操作    struct sembuf op[2]; // 定义操作,这里定义了两个操作    op[0].sem_num=0; //信号量的下标    op[0].sem_op=-1; //信号量的操作单位与类型  -就是阻塞(不够减就等待)    op[0].sem_flg=0; //操作标记 IPC_NOWAIT不管够不够减都要返回,够减就是正常方式返回,不够减异常方式返回  SEM_UNDO当程序异常退出,系统自动把操作恢复到原始值,用来解除死锁。一般这两个都用不到    while(1)    {        r=semop(semid,op,1); //val为2 执行2次就会阻塞        printf("解除阻塞\n");    }    return 0;}

输出两次“解除阻塞” 后阻塞


运行下面的程序 又可以开始输出"解除阻塞"

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/sem.h>union semun {    int              val;    /* Value for SETVAL */    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */    unsigned short  *array;  /* Array for GETALL, SETALL */    struct seminfo  *__buf;  /* Buffer for IPC_INFO                                (Linux-specific) */};int main(int argc, const char *argv[]){    key_t key;    int semid;    key=ftok(".",22);    if(key==-1) printf("ftok error:%m\n"),exit(-1);    //semid=semget(key,1,IPC_CREAT|IPC_EXCL|0666);    //if(semid==-1) printf("semget error:%m\n") ,exit(-1);    semid=semget(key,1,0);    //得到信号量    if(semid==-1) printf("semget error:%m\n") ,exit(-1);    printf("semid:%d\n",semid);    int r;        //对信号量进行阻塞操作    struct sembuf op[2]; // 定义操作,这里定义了两个操作    op[0].sem_num=0; //信号量的下标    op[0].sem_op=+1; //信号量的操作单位与类型  -就是阻塞(不够减就等待)    op[0].sem_flg=0; //操作标记 IPC_NOWAIT不管够不够减都要返回,够减就是正常方式返回,不够减异常方式返回  SEM_UNDO当程序异常退出,系统自动把操作恢复到原始值,用来解除死锁。一般这两个都用不到    while(1)    {        r=semop(semid,op,1); //val为2 执行2次就会阻塞        sleep(1);    }    return 0;}



0 0
原创粉丝点击