#include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> #define MSGKEY 75 struct msgform { long mtype; char mtext[1030]; }msg; int msgqid,i; void CLIENT() { int i; msgqid=msgget(MSGKEY,0777); for (i=10;i>=1;i--) { msg.mtype=i; printf("(client) sent \n"); msgsnd(msgqid,&msg,1024,0); } exit(0); } void SERVER() { msgqid=msgget(MSGKEY,0777|IPC_CREAT); do{ msgrcv(msgqid,&msg,1030,0,0); printf("(Server) recieved\n"); } while(msg.mtype!=1); msgctl(msgqid,IPC_RMID,0); exit(0); } void main() { while((i=fork())==-1); if(!i) SERVER(); while((i=fork())==-1); if(!i) CLIENT(); wait(0); wait(0); }解释一下这个代码。为什么不会一直创建进程?
时间: 2023-12-03 21:03:22 浏览: 34
这段代码实现了一个基于消息队列的进程间通信的例子,其中包括了一个客户端和一个服务端。主函数中首先通过fork()创建了两个子进程,一个子进程用来运行SERVER()函数,另一个子进程用来运行CLIENT()函数。在SERVER()函数中,首先调用msgget()函数创建了一个消息队列,然后通过do-while循环调用msgrcv()函数来接收从客户端发送过来的消息,直到收到类型为1的消息后,调用msgctl()函数删除消息队列并退出进程。在CLIENT()函数中,首先调用msgget()函数获取同一个消息队列,然后通过for循环不断地调用msgsnd()函数向消息队列中发送不同类型的消息。
对于为什么不会一直创建进程的问题,这是因为在主函数中使用了两个while循环,通过fork()函数创建进程后,父进程会返回子进程的PID,而子进程则返回0。因此在while循环中,只有其中一个分支会被执行,而另一个分支则会被跳过,从而避免了无限制地创建进程的问题。当两个子进程都创建成功后,主进程通过wait()函数等待它们的退出。
相关问题
解释代码#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define MSGKEY 75 struct msgform { long mt
这段代码定义了一个消息队列,在 Linux 系统中,消息队列是一种进程间通信的方式。代码中包含了以下头文件:
- sys/types.h:定义了系统调用所使用的数据类型,例如 pid_t、size_t 等。
- sys/ipc.h:定义了用于进程间通信的 IPC(Inter-Process Communication)相关函数和数据结构,例如消息队列、信号量、共享内存等。
- sys/msg.h:定义了消息队列相关的函数和数据结构,例如 msgget、msgsnd、msgrcv 等。
- stdio.h:定义了输入输出函数,例如 printf、scanf 等。
- stdlib.h:定义了内存管理函数,例如 malloc、free 等。
- unistd.h:定义了一些 UNIX 标准的函数和符号常量,例如 sleep、fork、getpid 等。
- string.h:定义了一些字符串处理函数,例如 memcpy、memset 等。
在代码中,使用了宏定义 MSGKEY 定义了消息队列的键值。结构体 msgform 定义了消息的格式,包含了一个长整型变量 mt 和一个字符数组 mtext。后面的代码中使用了 msgget 函数获取消息队列的标识符,使用了 msgsnd 函数发送消息,使用了 msgrcv 函数接收消息。
#include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> #define MSGKEY 75 struct msgform { long mtype; char mtext[1030]; }msg; int msgqid,i; void CLIENT() { int i; msgqid=msgget(MSGKEY,0777); for (i=10;i>=1;i--) { msg.mtype=i; printf("(client) sent \n"); msgsnd(msgqid,&msg,1024,0); 16 } exit(0); } void SERVER() { msgqid=msgget(MSGKEY,0777|IPC_CREAT); do{ msgrcv(msgqid,&msg,1030,0,0); printf("(Server) recieved\n"); } while(msg.mtype!=1); msgctl(msgqid,IPC_RMID,0); exit(0); } void main() { while((i=fork())==-1); if(!i) SERVER(); while((i=fork())==-1); if(!i) CLIENT(); wait(0); wait(0); }
这段代码实现了一个简单的消息队列通信程序,包括一个服务端和一个客户端。客户端向服务端发送一组消息,服务端接收消息并输出。具体实现如下:
1. 定义了一个消息结构体 msgform,包括消息类型和消息内容。
2. 在客户端函数 CLIENT() 中,首先获取消息队列的标识符 msgqid,然后利用 for 循环向服务端发送 10 组消息,每组消息的类型从 10 到 1 递减。发送消息使用 msgsnd 函数,其中第一个参数是消息队列标识符,第二个参数是指向消息结构体的指针,第三个参数是消息长度,第四个参数是消息发送标志。
3. 在服务端函数 SERVER() 中,首先创建一个消息队列并获取其标识符 msgqid,然后利用 do-while 循环接收客户端发送的消息,直到接收到类型为 1 的消息为止。接收消息使用 msgrcv 函数,其中第一个参数是消息队列标识符,第二个参数是指向消息结构体的指针,第三个参数是消息长度,第四个参数是消息类型,第五个参数是消息接收标志。
4. 最后在 main 函数中,使用 fork 函数创建服务端和客户端两个子进程,分别调用 SERVER() 和 CLIENT() 函数。使用 wait 函数等待两个子进程结束。
需要注意的是,在发送消息时,消息长度应该是 1024,而在接收消息时,消息长度应该是 1030。这是因为消息结构体中的 mtext 字段有 1030 字节,其中前 4 个字节是消息类型,后面 1026 个字节是消息内容。
相关推荐
![image/gif](https://img-home.csdnimg.cn/images/20210720083352.png)
![exe](https://img-home.csdnimg.cn/images/20210720083343.png)
![text/x-c](https://img-home.csdnimg.cn/images/20210720083646.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)