Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519912
  • 博文数量: 257
  • 博客积分: 1666
  • 博客等级: 上尉
  • 技术积分: 1535
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-02 23:02
文章分类

全部博文(257)

文章存档

2013年(2)

2012年(255)

分类:

2012-09-06 12:40:39

信号量函数定义如下:

#include
int semctl(int sem_id, int sem_num, int command, ...);
int semget(key_t key, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
semop

函数semop用来改变信号量的值:

int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);

第一个参数,sem_id,是由semget函数所返回的信号量标识符。第二个参数,sem_ops,是一个指向结构数组的指针,其中的每一个结构至少包含下列成员:

struct sembuf {
    short sem_num;
    short sem_op;
    short sem_flg;
}

第一个成员,sem_num,是信号量数目,通常为0,除非我们正在使用一个信号量数组。sem_op成员是信号量的变化量值。(我们可以以任何量改变信 号量值,而不只是1)通常情况下中使用两个值,-1是我们的P操作,用来等待一个信号量变得可用,而+1是我们的V操作,用来通知一个信号量可用。

最后一个成员,sem_flg,通常设置为SEM_UNDO。这会使得操作系统跟踪当前进程对信号量所做的改变,而且如果进程终止而没有释放这个信号量, 如果信号量为这个进程所占有,这个标记可以使得操作系统自动释放这个信号量。将sem_flg设置为SEM_UNDO是一个好习惯,除非我们需要不同的行 为。如果我们确实变我们需要一个不同的值而不是SEM_UNDO,一致性是十分重要的,否则我们就会变得十分迷惑,当我们的进程退出时,内核是否会尝试清 理我们的信号量。

semop的所用动作会同时作用,从而避免多个信号量的使用所引起的竞争条件。我们可以在手册页中了解关于semop处理更为详细的信息。

semctl

semctl函数允许信号量信息的直接控制:

int semctl(int sem_id, int sem_num, int command, ...);

第一个参数,sem_id,是由semget所获得的信号量标识符。sem_num参数是信号量数目。当我们使用信号量数组时会用到这个参数。通常,如果 这是第一个且是唯一的一个信号量,这个值为0。command参数是要执行的动作,而如果提供了额外的参数,则是unionsemun,根据X/OPEN 规范,这个参数至少包括下列参数:

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

许多版本的Linux在头文件(通常为sem.h)中定义了semun联合,尽管X/Open确认说我们必须定义我们自己的联合。如果我们发现我们确实需 要定义我们自己的联合,我们可以查看semctl手册页了解定义。如果有这样的情况,建议使用手册页中提供的定义,尽管这个定义与上面的有区别。

有多个不同的command值可以用于semctl。在这里我们描述两个会经常用到的值。要了解semctl功能的详细信息,我们应该查看手册页。

这两个通常的command值为:

SETVAL:用于初始化信号量为一个已知的值。所需要的值作为联合semun的val成员来传递。在信号量第一次使用之前需要设置信号量。
IPC_RMID:当信号量不再需要时用于删除一个信号量标识。

semctl函数依据command参数会返回不同的值。对于SETVAL与IPC_RMID,如果成功则会返回0,否则会返回-1。

信号量与共享内存的共同使用例子:

write 端:


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/ipc.h>
  6. #include <sys/shm.h>
  7. #include <errno.h>
  8. #include "sem.h"
  9.   
  10. typedef struct
  11. {
  12.     char buf[1024];
  13. }memory;
  14.   
  15. int main(int argc, const char *argv[])
  16. {
  17.     key_t key;
  18.     memory *p = NULL;
  19.     int shmid;
  20.     int create_flag = 0;
  21.     int sem_id;
  22.   
  23.     if ((key = ftok(".", 'a')) < 0)
  24.     {
  25.         perror("failed to get key");
  26.         exit(-1);
  27.     }
  28.   
  29.     if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)
  30.     {
  31.         if (errno == EEXIST)
  32.         {
  33.             if ((sem_id = semget(key, 1, 0666)) < 0)
  34.             {
  35.                 perror("failed to semget");
  36.                 exit(-1);
  37.             }
  38.         }
  39.     }
  40.   
  41.     init_sem(sem_id, 0);
  42.   
  43.     if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)
  44.     {
  45.         if (errno == EEXIST)
  46.         {
  47.             if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)
  48.             {
  49.                 perror("failed to shmget memory");
  50.                 exit(-1);
  51.             }
  52.         }
  53.         else
  54.         {
  55.             perror("failed to shmget");
  56.             exit(-1);
  57.         }
  58.     }
  59.     else
  60.         create_flag = 1;
  61.   
  62.     if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))
  63.     {
  64.         perror("failed to shmat memory");
  65.         exit(-1);
  66.     }
  67.   
  68.     while(1)
  69.     {
  70.         printf(">");
  71.         fgets(p->buf, sizeof(p->buf), stdin);
  72.         p->buf[strlen(p->buf) - 1] = 0;
  73.   
  74.         sem_v(sem_id);
  75.   
  76.         if (strncmp(p->buf, "quit", 4) == 0)
  77.             break;
  78.     }
  79.   
  80.     if (create_flag == 1)
  81.     {
  82.         if (shmdt(p) < 0)
  83.         {
  84.             perror("failed to shmdt memory");
  85.             exit(-1);
  86.         }
  87.   
  88.         if (shmctl(shmid, IPC_RMID, NULL) == -1)
  89.         {
  90.             perror("failed to delete share memory");
  91.             exit(-1);
  92.         }
  93.   
  94.         delete_sem(sem_id);
  95.     }
  96.   
  97.     return 0;
  98. }
read 端:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2.     #include <stdlib.h>
  3.     #include <string.h>
  4.     #include <sys/types.h>
  5.     #include <sys/ipc.h>
  6.     #include <sys/shm.h>
  7.     #include <errno.h>
  8.     #include "sem.h"
  9.       
  10.     typedef struct
  11.     {
  12.         char buf[1024];
  13.     }memory;
  14.       
  15.     int main(int argc, const char *argv[])
  16.     {
  17.         key_t key;
  18.         int shmid;
  19.         memory *p = NULL;
  20.         int create_flag = 0;
  21.         int sem_id;
  22.       
  23.         if ((key = ftok(".", 'a')) < 0)
  24.         {
  25.             perror("failed to get key");
  26.             exit(-1);
  27.         }
  28.       
  29.         if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)
  30.         {
  31.             if (errno == EEXIST)
  32.             {
  33.                 if ((sem_id = semget(key, 1, 0666)) < 0)
  34.                 {
  35.                     perror("failed to semget");
  36.                     exit(-1);
  37.                 }
  38.             }
  39.         }
  40.       
  41.         init_sem(sem_id, 0);
  42.       
  43.         if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)
  44.         {
  45.             if (errno == EEXIST)
  46.             {
  47.                 if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)
  48.                 {
  49.                     perror("failed to create share memory");
  50.                     exit(-1);
  51.                 }
  52.             }
  53.             else
  54.             {
  55.                 perror("failed to shmget");
  56.                 exit(-1);
  57.             }
  58.         }
  59.         else
  60.             create_flag = 1;
  61.       
  62.         if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))
  63.         {
  64.             perror("failed to shmat");
  65.             exit(-1);
  66.         }
  67.           
  68.         while(1)
  69.         {
  70.             sem_p(sem_id);
  71.       
  72.             if (strncmp(p->buf, "quit", 4) == 0)
  73.                 break;
  74.       
  75.             printf("recv: %s\n", p->buf);
  76.       
  77.         }
  78.       
  79.         if (create_flag == 1)
  80.         {
  81.             if (shmdt(p) < 0)
  82.             {
  83.                 perror("failed to shmdt");
  84.                 exit(-1);
  85.             }
  86.       
  87.             if (shmctl(shmid, IPC_RMID, NULL) == -1)
  88.             {
  89.                 perror("failed to delete share memory");
  90.                 exit(-1);
  91.             }
  92.       
  93.             delete_sem(sem_id);
  94.         }
  95.       
  96.         return 0;
  97.     }

信号量的封装:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2.     #include <stdlib.h>
  3.     #include <sys/types.h>
  4.     #include <sys/ipc.h>
  5.     #include <sys/sem.h>
  6.     #include <unistd.h>
  7.       
  8.     void init_sem(int , int );
  9.     void delete_sem(int );
  10.     void sem_p(int );
  11.     void sem_v(int );
  12.       
  13.     union semun
  14.     {
  15.         int val;
  16.         struct semid_ds *buf;
  17.         unsigned short *array;
  18.     };
  19.       
  20.     void init_sem(int sem_id, int init_value)
  21.     {
  22.         union semun sem_union;
  23.       
  24.         sem_union.val = init_value;
  25.       
  26.         if (semctl(sem_id, 0, SETVAL, sem_union) < 0)
  27.         {
  28.             perror("failed to init_sem");
  29.             exit(-1);
  30.         }
  31.       
  32.         return ;
  33.     }
  34.       
  35.     void delete_sem(int sem_id)
  36.     {
  37.         union semun sem_union;
  38.       
  39.         if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0)
  40.         {
  41.             perror("failed to delete_sem");
  42.             exit(-1);
  43.         }
  44.       
  45.         return ;
  46.     }
  47.       
  48.     void sem_p(int sem_id)
  49.     {
  50.         struct sembuf sem_b;
  51.       
  52.         sem_b.sem_num = 0;
  53.         sem_b.sem_op = -1;
  54.         sem_b.sem_flg = SEM_UNDO;
  55.       
  56.         if (semop(sem_id, &sem_b, 1) < 0)
  57.         {
  58.             perror("failed to sem_p");
  59.             exit(-1);
  60.         }
  61.       
  62.         return;
  63.     }
  64.       
  65.     void sem_v(int sem_id)
  66.     {
  67.         struct sembuf sem_b;
  68.       
  69.         sem_b.sem_num = 0;
  70.         sem_b.sem_op = 1;
  71.         sem_b.sem_flg = SEM_UNDO;
  72.       
  73.         if (semop(sem_id, &sem_b, 1) < 0)
  74.         {
  75.             perror("failed to sem_v");
  76.             exit(-1);
  77.         }
  78.       
  79.         return ;
  80.     }




阅读(429) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~