消息队列(3):在多进程中利用信号量进行同步、传递消息

1多进程操作函数

    (1)fork函数

    用于增加一个进程,返回的pid如果大于0,表示后续操作在父进程里执行;返回的pid如果等于0,表示后续操作在子进程里执行;返回pid小于0,表示增加进程失败。
    在fork函数执行前建立的局部变量,将在子进程中产生一份拷贝。原话是这样说的:The child process and the parent process run in separate memory spaces. At the time of fork() both memory spaces have the same content. “子进程和父进程运行在独立的内存空间中,fork函数执行时,两个内存空间有相同的内容。”当然这是针对一般的变量,有一些特殊的变量并不会被拷贝,这属于进阶内容了,这里暂不讨论。

    (2)wait函数

    在父进程中执行,等待子进程停止或销毁,原话:wait for a child process to stop or terminate.

2信号量操作函数

    信号量主要用于进程间同步。
    sem_post函数执行时,将信号量加1,然后执行后续的操作。
    sem_wait函数执行时,等待信号量,如果信号量大于1,则减1,然后执行以后的操作。否则一直等待在这里。

3.程序实例

    在下面的实例中,使用fork函数建立了两个进程,父进程执行完消息发送后,释放信号量;子进程收到信号量后再去读取信号。子进程执行完毕后进程销毁,这时父进程利用wait函数收到信息,再使用mq_unlink函数清除消息队列(外在表现是删除了消息队列缓存文件),程序退出。

执行结果:

child : before recv msg, pi is -1.000000.
father : msg id is 0x3A450.
father : send pi is 3.141590.
child : msg id is 0x52870.
child : recv pi is 3.141590.

4.源代码

// 消息队列:
// 2017-05-11
#include 
  
  
   
   
#include 
   
   
    
    
#include 
    
    
     
         //消息队列
#include 
     
     
      
          //多进程   (fork)
#include 
      
      
        //信号量 #include 
       
         //wait函数 #include 
        
          //定义了系统中大量的宏 struct MsgType { int len; float pi; }; sem_t mySem; int main() { mqd_t msgq_id; struct MsgType msg; unsigned int prio; const char *file = "\\mqex1"; int fpid = fork(); //产生一个子进程 // 进入父进程 if(fpid > 0) { msg.len = 8; msg.pi = 3.14159; // 新建或打开一个消息队列 msgq_id = mq_open(file, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, NULL); printf("father : msg id is 0x%X.\n",(unsigned int)msgq_id); fflush(stdout); if (msgq_id == (mqd_t) -1) { perror("mq_open error"); exit(1); } printf("father : send pi is %f.\n",msg.pi); fflush(stdout); // 发送消息 if (mq_send(msgq_id, (char*) &msg, sizeof(struct MsgType), prio) == -1) { perror("mq_send"); exit(1); } //发送信号量 sem_post(&mySem); // 关闭消息队列 if (mq_close(msgq_id) == -1) { perror("mq_close"); exit(1); } //等待子进程完成任务 //sleep(1); wait(NULL); // 删除消息队列缓存文件 if (mq_unlink(file) == -1) { perror("mq_unlink"); exit(1); } } //进入子进程 if(fpid == 0) { msg.len = 8; msg.pi = -1; printf("child : before recv msg, pi is %f.\n",msg.pi); fflush(stdout); // 新建或打开一个消息队列 msgq_id = mq_open(file, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, NULL); printf("child : msg id is 0x%X.\n",(unsigned int)msgq_id); if (msgq_id == (mqd_t) -1) { perror("mq_open error"); exit(1); } // 等待信号量 sem_wait(&mySem); // 接收消息 if (mq_receive(msgq_id, (char*) &msg, 8192, &prio) == -1) { perror("mq_receive"); exit(1); } printf("child : recv pi is %f.\n",msg.pi); fflush(stdout); // 关闭消息队列 if (mq_close(msgq_id) == -1) { perror("mq_close"); exit(1); } /* if (mq_unlink(file) == -1) { perror("mq_unlink"); exit(1); } */ } if(fpid<0) //开辟子进程失败则退出 { perror("fork"); exit(1); } return 0; } 
         
        
      
     
     
    
    
   
   
  
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值