IPC代表进程间通信,代表一组在线程和进程之间交换数据和消息的方法。
Android IPC Binder - onTransact() 等待前一个返回
我有一个使用 IPC 的应用程序。 我的主应用程序正在接收来自远程服务的单向回调。 收到这些回调后,我正在做一些及时的工作(1-20 秒)。 如果我明白
我需要帮助使用 C 和系统调用在 Ubuntu 中完成我的 schhol 项目。 该项目的目的是模拟船舶在港口之间运输不同种类货物的交通
父母有“m”条消息要发送给“n”个孩子。在每次迭代中,它向所有子节点发送一条消息。如果所有回复“已收到”,它会发送下一条消息。下面是我的代码 #包括 父母有“m”条消息要发送给“n”个孩子。在每次迭代中,它向所有子节点发送一条消息。如果所有回复“已收到”,它会发送下一条消息。下面是我的代码 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/wait.h> #include <stdio.h> #include <string.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #define MAX_LEN 50 struct details { int no; int id; char msg_text[MAX_LEN]; }; typedef struct msg_buf { long int msg_type; struct details d; } msg; char message[20][50] = { " ", "Message1", "Message2", "Message3", "Message4", "Message5", "Message6", "Message7", "Message8" }; int main(int argc, char *argv[]) { int id1, id2, n, m, i, j, status, p_id; pid_t pid; msg snd, rcvd; if (argc < 2) { perror("Too few arguments"); return -1; } n = atoi(argv[1]); m = atoi(argv[2]); id1 = msgget((key_t)78, IPC_CREAT | 0666); id2 = msgget((key_t)56, IPC_CREAT | 0666); if (id1 == -1 || id2 == -1) { printf("Error in creating message queue\n"); return -1; } p_id = getpid(); printf("\nQueues are created.\n\n"); for (i = 1; i <= n; i++) { pid = fork(); if (pid == 0) break; } if (pid == 0) { for (j = 1; j <= m; j++) { printf("Process %d waiting for message %d\n", getpid(), j); while (msgrcv(id1, &rcvd, sizeof(struct details), j + 1, IPC_NOWAIT) < 0) { } srand(time(0)); strcpy(snd.d.msg_text, "Received"); snd.msg_type = rcvd.msg_type; snd.d.no = rcvd.d.no; snd.d.id = getpid(); if (msgsnd(id2, &snd, sizeof(struct details), IPC_NOWAIT) < 0) { perror("msgsnd"); } else { printf("Reply sending successful for message %d for process %d\n", snd.d.no, snd.d.id); } } } if (p_id == getpid()) { for (j = 1; j <= m; j++) { strcpy(snd.d.msg_text, message[j]); snd.msg_type = j + 1; snd.d.no = j; if (msgsnd(id1, &snd, sizeof(struct details), 0) < 0) { perror("msgsnd"); } else { printf("Message %d sent- \t\t\t\t%s\n", j, snd.d.msg_text); } for (i = 1; i <= n; i++) { sleep(i); if (msgrcv(id2, &rcvd, sizeof(struct details), j + 1, 0) >= 0) { printf("Reply received from child %d for message %d - \t%s\n", rcvd.d.id, j, rcvd.d.msg_text); } } } wait(NULL); printf("Communication End.\n\n"); } } 我得到的输出是n=2,m=2是: Queues are created. Message 1 sent- Message1 Process 14804 waiting for message 1 Process 14805 waiting for message 1 Reply sending successful for message 1 for process 14804 Process 14804 waiting for message 2 Reply received from child 14804 for message 1 - Received 此后什么也没有打印。没有任何进展。问题是什么?如何解决这个问题? 最大的单一问题是在评论中提到的一个: AFAICS,您每次迭代发送一条消息,因此最多一个孩子可以阅读它。您不会向每个孩子发送一条消息。 任何给定的消息都可以被(最多)一个进程接收。对于 n 进程接收消息,您必须发送 n 消息。 其他问题主要是装饰性的。我使用了 GitHub 上我的 SOQ(堆栈溢出问题)存储库中可用的日志记录代码作为文件 stderr.c 和 stderr.h 在 src/libsoq 子目录中。一些消息被写入 stdout — 没有只接受文件流的函数,所以我使用 err_logmsg() 接受文件流、控制选项和退出状态(但函数不应该退出,所以这是未使用的)以及格式和参数。 结果是: /* SO 7592-2454 */ #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/wait.h> #include <unistd.h> #include "stderr.h" #define MAX_LEN 50 struct details { int no; int id; char msg_text[MAX_LEN]; }; typedef struct msg_buf { long int msg_type; struct details d; } msg; static char message[20][50] = { " ", "Message1", "Message2", "Message3", "Message4", "Message5", "Message6", "Message7", "Message8" }; static const char usestr[] = "num_kids num_msgs"; static void dump_message(const char *tag, const msg *info) { err_logmsg(stdout, err_getlogopts(), 0, "%s: type %ld (details: no %d, id %d, text [%s])\n", tag, info->msg_type, info->d.no, info->d.id, info->d.msg_text); } int main(int argc, char *argv[]) { err_setarg0(argv[0]); if (argc != 3) err_usage(usestr); int n = atoi(argv[1]); int m = atoi(argv[2]); int id1 = msgget((key_t)78, IPC_CREAT | 0666); int id2 = msgget((key_t)56, IPC_CREAT | 0666); if (id1 == -1 || id2 == -1) err_syserr("failed to create a message queue: "); pid_t p_id = getpid(); err_setlogopts(ERR_PID|ERR_MILLI); err_logmsg(stdout, err_getlogopts(), 0, "Queues are created.\n"); pid_t pid; for (int i = 1; i <= n; i++) { pid = fork(); if (pid == 0) break; } msg snd; msg rcvd; if (pid == 0) { for (int j = 1; j <= m; j++) { err_logmsg(stdout, err_getlogopts(), 0, "Waiting for message %d\n", j); while (msgrcv(id1, &rcvd, sizeof(struct details), j + 1, IPC_NOWAIT) < 0) err_syserr("msgrcv() returned with error status: "); dump_message("Message received", &rcvd); strcpy(snd.d.msg_text, "Received"); snd.msg_type = rcvd.msg_type; snd.d.no = rcvd.d.no; snd.d.id = getpid(); if (msgsnd(id2, &snd, sizeof(struct details), IPC_NOWAIT) < 0) err_sysrem("msgsnd() failed: "); else dump_message("Message sent", &snd); } err_logmsg(stdout, err_getlogopts(), 0, "Child process complete\n"); exit(EXIT_SUCCESS); } if (p_id == getpid()) { for (int j = 1; j <= m; j++) { strcpy(snd.d.msg_text, message[j]); snd.msg_type = j + 1; snd.d.no = j; for (int i = 0; i < n; i++) { if (msgsnd(id1, &snd, sizeof(struct details), 0) < 0) err_sysrem("msgsnd() failed: "); else dump_message("Message sent", &snd); } for (int i = 1; i <= n; i++) { err_logmsg(stdout, err_getlogopts(), 0, "Dozing for %d seconds\n", i); sleep(i); if (msgrcv(id2, &rcvd, sizeof(struct details), j + 1, 0) >= 0) dump_message("Reply received", &rcvd); else err_syserr("msgrcv() failed: "); } } int corpse; int status; while ((corpse = wait(&status)) > 0) err_remark("Child %d exited with status 0x%.4X\n", corpse, status); err_logmsg(stdout, err_getlogopts(), 0, "Communication End.\n\n"); } return 0; } 有大量的日志记录,因为我需要看看发生了什么。代码应该验证 n 和 m 的值(它们应该至少是 1 并且不超过一些微弱的理智数字(例如 10,但会有一个或两个值(枚举或定义常数)来限制可接受的范围。 这是一个示例输出(源代码msg79.c,程序msg79): $ ./msg79 2 3 msg79: 2023-04-03 21:36:38.215 - pid=67247: Queues are created. msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1]) msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1]) msg79: 2023-04-03 21:36:38.217 - pid=67247: Dozing for 1 seconds msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 1 msg79: 2023-04-03 21:36:38.217 - pid=67249: Waiting for message 1 msg79: 2023-04-03 21:36:38.217 - pid=67248: Message received: type 2 (details: no 1, id 1, text [Message1]) msg79: 2023-04-03 21:36:38.217 - pid=67249: Message received: type 2 (details: no 1, id 1, text [Message1]) msg79: 2023-04-03 21:36:38.217 - pid=67248: Message sent: type 2 (details: no 1, id 67248, text [Received]) msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 2 msg79: 2023-04-03 21:36:38.217 - pid=67249: Message sent: type 2 (details: no 1, id 67249, text [Received]) msg79: 2023-04-03 21:36:38.218 - pid=67248: Message received: type 3 (details: no 2, id 1, text [Message2]) msg79: 2023-04-03 21:36:38.218 - pid=67249: Waiting for message 2 msg79: 2023-04-03 21:36:38.218 - pid=67249: Message received: type 3 (details: no 2, id 1, text [Message2]) msg79: 2023-04-03 21:36:38.218 - pid=67248: Message sent: type 3 (details: no 2, id 67248, text [Received]) msg79: 2023-04-03 21:36:38.218 - pid=67249: Message sent: type 3 (details: no 2, id 67249, text [Received]) msg79: 2023-04-03 21:36:38.218 - pid=67248: Waiting for message 3 msg79: 2023-04-03 21:36:38.219 - pid=67249: Waiting for message 3 msg79: 2023-04-03 21:36:38.219 - pid=67248: Message received: type 4 (details: no 3, id 1, text [Message3]) msg79: 2023-04-03 21:36:38.219 - pid=67249: Message received: type 4 (details: no 3, id 1, text [Message3]) msg79: 2023-04-03 21:36:38.219 - pid=67248: Message sent: type 4 (details: no 3, id 67248, text [Received]) msg79: 2023-04-03 21:36:38.219 - pid=67249: Message sent: type 4 (details: no 3, id 67249, text [Received]) msg79: 2023-04-03 21:36:38.219 - pid=67248: Child process complete msg79: 2023-04-03 21:36:38.219 - pid=67249: Child process complete msg79: 2023-04-03 21:36:39.219 - pid=67247: Reply received: type 2 (details: no 1, id 67248, text [Received]) msg79: 2023-04-03 21:36:39.219 - pid=67247: Dozing for 2 seconds msg79: 2023-04-03 21:36:41.220 - pid=67247: Reply received: type 2 (details: no 1, id 67249, text [Received]) msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2]) msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2]) msg79: 2023-04-03 21:36:41.220 - pid=67247: Dozing for 1 seconds msg79: 2023-04-03 21:36:42.221 - pid=67247: Reply received: type 3 (details: no 2, id 67248, text [Received]) msg79: 2023-04-03 21:36:42.221 - pid=67247: Dozing for 2 seconds msg79: 2023-04-03 21:36:44.223 - pid=67247: Reply received: type 3 (details: no 2, id 67249, text [Received]) msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3]) msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3]) msg79: 2023-04-03 21:36:44.223 - pid=67247: Dozing for 1 seconds msg79: 2023-04-03 21:36:45.227 - pid=67247: Reply received: type 4 (details: no 3, id 67248, text [Received]) msg79: 2023-04-03 21:36:45.227 - pid=67247: Dozing for 2 seconds msg79: 2023-04-03 21:36:47.227 - pid=67247: Reply received: type 4 (details: no 3, id 67249, text [Received]) msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67249 exited with status 0x0000 msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67248 exited with status 0x0000 msg79: 2023-04-03 21:36:47.228 - pid=67247: Communication End. $
我正在编写一个使用进程间消息队列的 C 程序。我正在尝试重现进程 J(法官)和 n-child 进程之间的拍卖。程序从输入文件 txt 和 nu...
我的理解是你不能从渲染进程回复从主进程发送的事件。 当通信从渲染器进程到主进程时,你可以做同样的事情
我尝试在 C 中使用消息队列模拟宾果游戏。 我的程序这样做: 父亲应该分发孩子的卡片,而不是特定的顺序。 孩子们收到卡片并将其打印在
如何在守护进程中使用具有多个进程的单个命名管道 - Bash 中的客户端 IPC?
我正在尝试编写一个脚本来启动一个守护进程,该守护进程同时通过两个命名管道 $FIFO.out 和 $FIFO.in 分别传输其输出和输入。我想做的是给客户进程
如何在 Electron 中启动网络套接字并从 utilityProcess 发回数据
我正在尝试使用新的 utilityProcess 模块进行后台工作,而不是 Electron 中的隐藏渲染器。 我似乎找不到任何好的例子。使用。该文档相当简洁。
我写了一个 shm 结构如下: 类 ShmWorker { 民众: ShmWorker() = 默认值; 虚拟 ~ShmWorker() { shmdt(m_data); shmctl(shmid, IPC_RMID, 0); // 这就是问题所在...
如何在不同conda环境的两个不同python进程之间交换数据?
A 和 B 两个 python 脚本存在兼容性问题,需要为它们提供单独的 conda 环境。这是场景。当脚本 A 运行时,它向进程 B 发送数据(脚本 B 运行在一个
我需要一些帮助来理解如何在 C 中使用条件变量来解决练习。这是一个小例子: #包括 #包括 #包括 我需要一些帮助来理解如何在 C 中使用条件变量来解决练习。这是一个小例子: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #define OKTOWRITE "/oktowrite" #define MESSAGE "/message" #define MUTEX "/lock" int main(int argc, char** argv) { pthread_cond_t* condition; pthread_mutex_t *mutex; char* message; int des_cond, des_msg, des_mutex; int mode = S_IRWXU | S_IRWXG; des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode); if (des_mutex < 0) { perror("failure on shm_open on des_mutex"); exit(1); } if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) { perror("Error on ftruncate to sizeof pthread_cond_t\n"); exit(-1); } mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0); if (mutex == MAP_FAILED ) { perror("Error on mmap on mutex\n"); exit(1); } pthread_mutex_init(mutex, NULL ); des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode); if (des_cond < 0) { perror("failure on shm_open on des_cond"); exit(1); } if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) { perror("Error on ftruncate to sizeof pthread_cond_t\n"); exit(-1); } condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t), PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0); if (condition == MAP_FAILED ) { perror("Error on mmap on condition\n"); exit(1); } pthread_cond_init(condition, NULL ); if (!fork()) { sleep(3); pthread_mutex_lock(mutex); pthread_cond_signal(condition); pthread_mutex_unlock(mutex); printf("son signaled\n"); exit(0); } else { printf("wait on condition\n"); pthread_mutex_lock(mutex); pthread_cond_wait(condition, mutex); pthread_mutex_unlock(mutex); printf("Signaled by son process, wake up\n"); pthread_mutex_destroy(mutex); pthread_cond_destroy(condition); shm_unlink(OKTOWRITE); shm_unlink(MESSAGE); shm_unlink(MUTEX); return 0; } } 问题是进程的父亲继续被锁定,即使在儿子发出信号之后也是如此。一切都在共享内存中(使用shm_open和mmap)所以两个进程的条件应该相同。 在调用 wait 或 signal 之前锁定互斥锁可能是我犯了一个错误吗? 编辑: 感谢所有帮助过我的人。这是标有关键部分的正确代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #define OKTOWRITE "/condwrite" #define MESSAGE "/msg" #define MUTEX "/mutex_lock" int main(int argc, char** argv) { pthread_cond_t* condition; pthread_mutex_t* mutex; char* message; int des_cond, des_msg, des_mutex; int mode = S_IRWXU | S_IRWXG; des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode); if (des_mutex < 0) { perror("failure on shm_open on des_mutex"); exit(1); } if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) { perror("Error on ftruncate to sizeof pthread_cond_t\n"); exit(-1); } mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0); if (mutex == MAP_FAILED ) { perror("Error on mmap on mutex\n"); exit(1); } des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode); if (des_cond < 0) { perror("failure on shm_open on des_cond"); exit(1); } if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) { perror("Error on ftruncate to sizeof pthread_cond_t\n"); exit(-1); } condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t), PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0); if (condition == MAP_FAILED ) { perror("Error on mmap on condition\n"); exit(1); } /* HERE WE GO */ /**************************************/ /* set mutex shared between processes */ pthread_mutexattr_t mutexAttr; pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(mutex, &mutexAttr); /* set condition shared between processes */ pthread_condattr_t condAttr; pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED); pthread_cond_init(condition, &condAttr); /*************************************/ if (!fork()) { sleep(10); pthread_mutex_lock(mutex); pthread_cond_signal(condition); printf("son signaled\n"); pthread_mutex_unlock(mutex); exit(0); } else { printf("father waits on condition\n"); pthread_mutex_lock(mutex); pthread_cond_wait(condition, mutex); pthread_mutex_unlock(mutex); printf("Signaled by son process, wake up!!!!!!!!\n"); pthread_condattr_destroy(&condAttr); pthread_mutexattr_destroy(&mutexAttr); pthread_mutex_destroy(mutex); pthread_cond_destroy(condition); shm_unlink(OKTOWRITE); shm_unlink(MESSAGE); shm_unlink(MUTEX); } return 0; } 要在进程之间共享,需要通过正确初始化的属性相应地初始化互斥量:http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setpshared.html #include <pthread.h> ... pthread_mutex_t * pmutex = NULL; pthread_mutexattr_t attrmutex; /* Initialise attribute to mutex. */ pthread_mutexattr_init(&attrmutex); pthread_mutexattr_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED); /* Allocate memory to pmutex here. */ /* Initialise mutex. */ pthread_mutex_init(pmutex, &attrmutex); /* Use the mutex. */ /* Clean up. */ pthread_mutex_destroy(pmutex); pthread_mutexattr_destroy(&attrmutex); (为了本示例的可读性,省略了错误检查) 这同样适用于应该在进程之间共享的条件变量:http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setpshared.html #include <pthread.h> ... pthread_cond_t * pcond = NULL; pthread_condattr_t attrcond; /* Initialise attribute to condition. */ pthread_condattr_init(&attrcond); pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED); /* Allocate memory to pcond here. */ /* Initialise condition. */ pthread_cond_init(pcond, &attrcond); /* Use the condition. */ /* Clean up. */ pthread_cond_destroy(pcond); pthread_condattr_destroy(&attrcond); (为了本示例的可读性,省略了错误检查) 另请参阅此答案:https://stackoverflow.com/a/2390670/694576 等待一个条件之前应该有一个 while 语句,像这样: pthread_mutex_lock(mutex); while(!conditionSatisfied) pthread_cond_wait(condition, mutex); pthread_mutex_unlock(mutex); while 信号应该通过以下方式完成: pthread_mutex_lock(mutex); conditionSatisfied = true; pthread_cond_signal(condition); pthread_mutex_unlock(mutex); 是的,必须在pthread_cond_wait之前锁定互斥量,但不必为pthread_cond_signal锁定。如果你回头看看你的代码,你会发现互斥量将被解锁两次,这是错误的标志......孩子也有可能在已被父母破坏的互斥量上调用解锁...... 顺便说一下,睡眠并不能保证父进程会先执行。为了确保这一点,您将需要……一个条件变量……
我想设计一个共享内存来在多个进程之间传递数据。 在多线程中,我需要 pthread_mutex_t 来投影临界区。 所以我想在...中分配一个 pthread_mutex_t
尝试在 Windows 10 中打开现有命名管道 - errno 22,无效参数,但为什么呢?
我正在编写/试验需要连接到 Windows 10 中现有命名管道的 python 脚本。我正在使用 Python 3.8。 命名管道 具体来说,我正在尝试连接到名为
我们有一个 UWP(Microsoft Store 分布式)应用程序,我们的客户希望通过他的软件进行控制。主要目标是客户可以控制应用程序(就好像用户会进行交互
在管道通信通道中,如果一个进程向管道写入的字节少于PIPE_BUF,那么从同一个管道读取的另一个进程的读操作是否可以同时看到一部分
我有这样一种情况,一个进程每 100 毫秒将 512 字节的数据写入管道,而另一个进程不断地从同一个管道读取数据。读取完整需要三个读取操作...
在 Linux 中从共享相同文件描述符的多个线程写入同一个管道是线程安全的吗?
我有一个有两个线程的 Linux 进程,它们共享同一个文件描述符,每 100 毫秒将 400 字节的数据写入同一个管道。我想知道 POSIX 是否保证这是线程安全的或...
启动使用来自 Python 进程的数据维护 B 树的 C/C++ 进程
我正在用 Python 实现一个数据库,并希望通过 B 树为某些属性维护二级索引。有没有一种方法可以初始化为 P...维护 B 树的 C 或 C++ 进程?
我正在研究用POSIX共享内存来代替POSIX消息队列进行IPC。我计划制作一个足够大的共享内存区域,以容纳50条每条750字节的消息。这些消息将在...
在文档中的Ruby IO.pipe例子中,一个消息是通过进程传递的。我想做一些类似的事情,但有两个区别:使用线程而不是进程使用一个......。