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

来源:互联网 发布:mac版foxmail邮箱设置 编辑:程序博客网 时间:2024/06/08 07:16

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
原创粉丝点击