高级编程之进程间通信(三)

来源:互联网 发布:百度输入法制作软件 编辑:程序博客网 时间:2024/05/16 08:54

                                      进程间通信(三)

 

IPC 通信之 ==》信号量集===》信号灯
 线程中用的是  posix无名信号量
 进程中用的是  system V 的信号灯

框架: key ==》申请信号量 ==》PV操作  ===>关闭信号量
       semget        semop         semctl


#include <sys/sem.h>

原型:int semget(key_t key, int nsems, int semflg);
功能:该函数可以向内核提出信号量集的对象申请。
参数:key  唯一键值
   nsems  要申请的信号量个数
   semflg 要申请的信号量权限,第一次申请用IPC_CREAT
      以后申请要用IPC_EXCL 检测
返回值:成功 返回一个信号量id   semid
  失败  -1;


pv操作

原型:int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:通过该函数可以将semid中的信号量的值做调整完成PV操作。
参数:semid  信号量id
   sops   信号量集的结构体指针,结构如下:
   struct sembuf
   {
     unsigned short sem_num;  //要操作的信号量集中信号量的编号,从0开始
     short sem_op;   //pv操作的值,如果为 -1 表示申请资源 p操作
                    如果为 +1 表示释放资源 v操作
              如果是0 表示阻塞等待

        short sem_flg;  //0 表示以阻塞方式执行信号量
         //IPC_NOWAIT 表示以非阻塞方式执行信号量
   }
   nsops  要操作的信号量的个数。
返回值:成功  0
  失败  -1;

通常将以上函数自定义封装:

int my_sem_wait(int id,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = -1; ///// 0 表示阻塞等待
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

int my_sem_post(int id ,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = 1;
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

属性操作:

原型:int semctl(int semid, int semnum, int cmd, ...);
功能:通过该函数可以修改信号量的属性和删除信号量
参数:semid 要操作的信号量集
   semnum  要操作的信号的编号
   cmd   ==》IPC_RMID  ===》删除信号量用。
     ==》SETVAL   ===》设置信号量值用。
   ==》GETVAL   ==》获取信号值用。

   ...可变长参数  IPC_RMID  该参数无效。
              SETVAL/GETVAL 结构如下

练习:设计两个进程,完成如下功能:
   进程1 获取用户输入信息,写入共享内存。
   进程2 实时读取共享内存中的数据并打印,同时统计字符串的长度。
   当用户输入quit的时候两个进程同时退出。

   要求:必须用到共享内存和信号量。

 

 

 

IPC 通信之 ==》信号量集===》信号灯
 线程中用的是  posix无名信号量
 进程中用的是  system V 的信号灯

框架: key ==》申请信号量 ==》PV操作  ===>关闭信号量
       semget        semop         semctl


#include <sys/sem.h>

原型:int semget(key_t key, int nsems, int semflg);
功能:该函数可以向内核提出信号量集的对象申请。
参数:key  唯一键值
   nsems  要申请的信号量个数
   semflg 要申请的信号量权限,第一次申请用IPC_CREAT
      以后申请要用IPC_EXCL 检测
返回值:成功 返回一个信号量id   semid
  失败  -1;


pv操作

原型:int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:通过该函数可以将semid中的信号量的值做调整完成PV操作。
参数:semid  信号量id
   sops   信号量集的结构体指针,结构如下:
   struct sembuf
   {
     unsigned short sem_num;  //要操作的信号量集中信号量的编号,从0开始
     short sem_op;   //pv操作的值,如果为 -1 表示申请资源 p操作
                    如果为 +1 表示释放资源 v操作
              如果是0 表示阻塞等待

        short sem_flg;  //0 表示以阻塞方式执行信号量
         //IPC_NOWAIT 表示以非阻塞方式执行信号量
   }
   nsops  要操作的信号量的个数。
返回值:成功  0
  失败  -1;

通常将以上函数自定义封装:

int my_sem_wait(int id,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = -1; ///// 0 表示阻塞等待
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

int my_sem_post(int id ,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = 1;
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

属性操作:

原型:int semctl(int semid, int semnum, int cmd, ...);
功能:通过该函数可以修改信号量的属性和删除信号量
参数:semid 要操作的信号量集
   semnum  要操作的信号的编号
   cmd   ==》IPC_RMID  ===》删除信号量用。
     ==》SETVAL   ===》设置信号量值用。
   ==》GETVAL   ==》获取信号值用。

   ...可变长参数  IPC_RMID  该参数无效。
              SETVAL/GETVAL 结构如下

练习:设计两个进程,完成如下功能:
   进程1 获取用户输入信息,写入共享内存。
   进程2 实时读取共享内存中的数据并打印,同时统计字符串的长度。
   当用户输入quit的时候两个进程同时退出。

   要求:必须用到共享内存和信号量。

 

 

IPC 通信之 ==》信号量集===》信号灯
 线程中用的是  posix无名信号量
 进程中用的是  system V 的信号灯

框架: key ==》申请信号量 ==》PV操作  ===>关闭信号量
       semget        semop         semctl


#include <sys/sem.h>

原型:int semget(key_t key, int nsems, int semflg);
功能:该函数可以向内核提出信号量集的对象申请。
参数:key  唯一键值
   nsems  要申请的信号量个数
   semflg 要申请的信号量权限,第一次申请用IPC_CREAT
      以后申请要用IPC_EXCL 检测
返回值:成功 返回一个信号量id   semid
  失败  -1;


pv操作

原型:int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:通过该函数可以将semid中的信号量的值做调整完成PV操作。
参数:semid  信号量id
   sops   信号量集的结构体指针,结构如下:
   struct sembuf
   {
     unsigned short sem_num;  //要操作的信号量集中信号量的编号,从0开始
     short sem_op;   //pv操作的值,如果为 -1 表示申请资源 p操作
                    如果为 +1 表示释放资源 v操作
              如果是0 表示阻塞等待

        short sem_flg;  //0 表示以阻塞方式执行信号量
         //IPC_NOWAIT 表示以非阻塞方式执行信号量
   }
   nsops  要操作的信号量的个数。
返回值:成功  0
  失败  -1;

通常将以上函数自定义封装:

int my_sem_wait(int id,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = -1; ///// 0 表示阻塞等待
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

int my_sem_post(int id ,int sem)
{
 struct sembuf mysem;
 mysem.sem_num = sem;
 mysem.sem_op  = 1;
 mysem.sem_flg = 0;

 if( semop(id,&mysem,1) < 0)
  return -1;
 else
  return 0;
}

属性操作:

原型:int semctl(int semid, int semnum, int cmd, ...);
功能:通过该函数可以修改信号量的属性和删除信号量
参数:semid 要操作的信号量集
   semnum  要操作的信号的编号
   cmd   ==》IPC_RMID  ===》删除信号量用。
     ==》SETVAL   ===》设置信号量值用。
   ==》GETVAL   ==》获取信号值用。

   ...可变长参数  IPC_RMID  该参数无效。
              SETVAL/GETVAL 结构如下

练习:设计两个进程,完成如下功能:
   进程1 获取用户输入信息,写入共享内存。
   进程2 实时读取共享内存中的数据并打印,同时统计字符串的长度。
   当用户输入quit的时候两个进程同时退出。

   要求:必须用到共享内存和信号量。

 

0 0