我正在通過訊息學習行程間通信。
在以下代碼片段中,我fork()在父行程和子行程之間應用和發送訊息。
我期望“1 - 2 - 3 - 4”控制臺輸出。然而,我得到了“1 - 2”,在此之后,程式似乎msgrcv在列印“3”之前永遠卡在了線上。誰能告訴代碼有什么問題?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define BUF_SIZE 16
#define MSG_KEY1 75
#define MSG_KEY2 76
struct msgform
{
long mtype;
char mbuf[BUF_SIZE];
long mind;
} msg;
struct msgping
{
long mtype;
long ping ;
} msgPing;
int main() {
if(fork() == 0) {
// child process
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
msg.mtype = 1;
msgPing.mtype = 1;
printf("1 - started, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
msgrcv(msgid2, &msg, sizeof(msg), 1, 0);
printf("3 - msg received, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
msgctl(msgid1, IPC_RMID, 0);
msgctl(msgid2, IPC_RMID, 0);
return 0;
}
//parent process
sleep(1);
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("2 - msgPing received, sending msg\n");
msgsnd(msgid2, &msg, sizeof(msg), 0);
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("4 - msgPing received, finished\n");
return 0;
}
uj5u.com熱心網友回復:
問題在于這里的訊息型別初始化:
msg.mtype = 1;
msgPing.mtype = 1;
這些值僅在孩子中初始化。當父級嘗試在 中發送訊息時msg,mtype尚未設定,因此子級會無休止地等待 的訊息mtype 1,而該訊息永遠不會到達。
要么在 之前設定這兩個值fork(),要么在父級和子級中設定它們,都可以使這項作業:
$ ./msg
1 - started, sending msgPing
3 - msg received, sending msgPing
2 - msgPing received, sending msg
4 - msgPing received, finished
大約一秒鐘后。
uj5u.com熱心網友回復:
你只設定mtype在孩子而不是父母。
此外,msgctl子行程中的呼叫正在msgrcv與父行程中的 final競爭。也就是說,子行程可能會在父行程有機會完成其最終msgctl呼叫之前完成呼叫msgrcv。
而且,我認為,孩子的return 0;應該是exit(0);防止落入父代碼。
在下面重構的代碼中,我使用cpp條件來表示舊的/損壞的與新的/固定的代碼:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
這是重構后的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#if 1
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#endif
#define BUF_SIZE 16
#define MSG_KEY1 75
#define MSG_KEY2 76
struct msgform {
long mtype;
char mbuf[BUF_SIZE];
long mind;
} msg;
struct msgping {
long mtype;
long ping;
} msgPing;
#define ONERR(_fd) \
do { \
if (_fd >= 0) \
break; \
printf("msgget error " #_fd " at line %d cldpid=%d -- %s\n", \
__LINE__,cldpid,strerror(errno)); \
exit(1); \
} while (0)
int
main()
{
#if 0
if (fork() == 0) {
#else
pid_t cldpid = fork();
if (cldpid == 0) {
#endif
// child process
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
ONERR(msgid1);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
ONERR(msgid2);
msg.mtype = 1;
msgPing.mtype = 1;
printf("1 - started, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
msgrcv(msgid2, &msg, sizeof(msg), 1, 0);
printf("3 - msg received, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
#if 0
msgctl(msgid1, IPC_RMID, 0);
msgctl(msgid2, IPC_RMID, 0);
#endif
#if 0
return 0;
#else
exit(0);
#endif
}
// parent process
sleep(1);
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
ONERR(msgid1);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
ONERR(msgid2);
// NOTE/FIX: the parent needs to set this as well as the child
#if 1
msg.mtype = 1;
msgPing.mtype = 1;
#endif
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("2 - msgPing received, sending msg\n");
msgsnd(msgid2, &msg, sizeof(msg), 0);
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("4 - msgPing received, finished\n");
#if 1
waitpid(cldpid,NULL,0);
msgctl(msgid1, IPC_RMID, 0);
msgctl(msgid2, IPC_RMID, 0);
#endif
return 0;
}
當我完成msgsnd/msgrcv實時、關鍵任務、生產代碼時,我在兩個方向上都使用了一個 msgid,使用了不同的 mtype值(例如,mtype = 1對于父級和mtype = 2ping)。
這是一個進一步清理和簡化的版本:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#if 1
#include <sys/wait.h>
#endif
#define BUF_SIZE 16
#define MSG_KEY1 75
#define MSG_KEY2 76
struct msgform {
long mtype;
char mbuf[BUF_SIZE];
long mind;
} msg;
struct msgping {
long mtype;
long ping;
} msgPing;
enum {
MSGTYPE = 1,
MSGPING = 2,
};
int
main(void)
{
int msgid = msgget(MSG_KEY1, 0666 | IPC_CREAT);
pid_t cldpid = fork();
msg.mtype = MSGTYPE;
msgPing.mtype = MSGPING;
if (cldpid == 0) {
sleep(1);
printf("1 - started, sending msgPing\n");
msgsnd(msgid, &msgPing, sizeof(msgPing), 0);
msgrcv(msgid, &msg, sizeof(msg), MSGTYPE, 0);
printf("3 - msg received, sending msgPing\n");
msgsnd(msgid, &msgPing, sizeof(msgPing), 0);
exit(0);
}
// parent process
sleep(1);
msgrcv(msgid, &msgPing, sizeof(msgPing), MSGPING, 0);
printf("2 - msgPing received, sending msg\n");
msgsnd(msgid, &msg, sizeof(msg), 0);
msgrcv(msgid, &msgPing, sizeof(msgPing), MSGPING, 0);
printf("4 - msgPing received, finished\n");
waitpid(cldpid,NULL,0);
msgctl(msgid, IPC_RMID, 0);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/361334.html
上一篇:如何從C中的佇列中取出最小的元素
下一篇:C輸入不會添加到陣列串列
