C 中两个进程共享内存?

发布于 2024-12-16 16:47:51 字数 1118 浏览 4 评论 0原文

我想做以下事情:

父进程创建一个子进程。然后子进程从用户那里读取 n 个 int 并将它们存储在共享内存中。然后父进程显示它们。

我达到以下目的:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSIZE 27
int main() {
   int shmid;
   int *shm;
   int *n;

   if(fork() == 0) {
      shmid = shmget(2009, SHMSIZE, 0);
      shm = shmat(shmid, 0, 0);
      n = shm;
      int i;
      for(i=0; i<5; i++) {
         printf("Enter number<%i>: ", i);
         scanf("%d", n++);
      }
      printf ("Child wrote <%d>\n",shm);
      shmdt(shm);
   }
   else {
      wait();
      int *s;
      shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
      shm = shmat(shmid, 0, 0);
      s = shm;
      wait(NULL);
      printf ("Parent reads <%d>\n",shm) ;
      shmdt(shm);
      shmctl(shmid, IPC_RMID, NULL);
   }
   return 0;
}

输出就是这一行:

Enter number<1>:

如果我输入一个数字,比如说 25,它会输出:

Parent reads <r>

r: random -ve number 每次执行代码时都会更改

它永远不会浏览了子进程代码!我这样做的方式不对吗?

I want to do the following:

Parent process creates a child process. Then the child process reads n int's from the user and store them in a shared memory. The parent process then displays them.

I reached the following:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSIZE 27
int main() {
   int shmid;
   int *shm;
   int *n;

   if(fork() == 0) {
      shmid = shmget(2009, SHMSIZE, 0);
      shm = shmat(shmid, 0, 0);
      n = shm;
      int i;
      for(i=0; i<5; i++) {
         printf("Enter number<%i>: ", i);
         scanf("%d", n++);
      }
      printf ("Child wrote <%d>\n",shm);
      shmdt(shm);
   }
   else {
      wait();
      int *s;
      shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
      shm = shmat(shmid, 0, 0);
      s = shm;
      wait(NULL);
      printf ("Parent reads <%d>\n",shm) ;
      shmdt(shm);
      shmctl(shmid, IPC_RMID, NULL);
   }
   return 0;
}

And the output is just this line:

Enter number<1>:

And if I entered a number, let's say 25, it outputs this:

Parent reads <r>

r: random -ve number changes every time I execute the code

It never went through the child process code ! Am I doing this in a wrong way ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

佼人 2024-12-23 16:47:51

好的,最好收集答案......

您的程序存在几个问题。如果您在构建时启用警告(我使用 -Wall -Wextra),其中很多警告将非常明显。

前两个问题我已经在评论中提到过,但我在这里解释一下:

  1. 第一个问题是对 wait() 的调用。 C 或 POSIX 中没有不带参数的 wait 函数。
  2. 第二个问题是 scanf 调用,您使用 *++ 调用它,其中 *n 接受 n 指向的内存很可能会导致崩溃。删除星号。
  3. 第三个问题是您将共享内存视为整数数组(带有n)和字符串。你实际上不可能两者都做,只能选择其中之一。
  4. 您在父进程中创建共享内存,但等待子进程完成后再创建内存。
  5. 父进程和子进程之间存在竞争条件,因为共享内存可能是在子进程尝试访问它之后创建的。

编辑 我想出了这个,这似乎对我有用。我对我更改的内容添加了评论。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/wait.h>  /* Needed for the wait function */
#include <unistd.h>    /* needed for the fork function */
#include <string.h>    /* needed for the strcat function */
#define SHMSIZE 27
int main() {
   int shmid;
   char *shm;

   if(fork() == 0) {
      shmid = shmget(2009, SHMSIZE, 0);
      shm = shmat(shmid, 0, 0);
      char *s = (char *) shm;
      *s = '\0';  /* Set first location to string terminator, for later append */
      int i;
      for(i=0; i<5; i++) {
         int n;  /* Variable to get the number into */
         printf("Enter number<%i>: ", i);
         scanf("%d", &n);

         char number[20];
         sprintf(number, "%d", n);  /* Convert the number to string */
         strcat(s, number);  /* Append the number to the string */
      }
      strcat(s, "\n");  /* Append newline */
      printf ("Child wrote <%s>\n",shm);
      shmdt(shm);
   }
   else {
      /* Variable s removed, it wasn't used */
      /* Removed first call to wait as it held up parent process */
      shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
      shm = shmat(shmid, 0, 0);
      wait(NULL);
      printf ("Parent reads <%s>\n",shm) ;
      shmdt(shm);
      shmctl(shmid, IPC_RMID, NULL);
   }
   return 0;
}

请注意,上面列表中的第 5 点尚未解决。

Ok, better collect in an answer instead...

There are several problems with you program. If you enable warnings when building (I use -Wall -Wextra) a lot of them will be quite evident.

The first two problems I already mentioned in my comments, but I explain them here:

  1. The first is the call to wait(). There is no wait function in C or POSIX that takes no argument.
  2. The second problem is the scanf call, you are calling it with *++, where *n takes the value of the memory pointed to by n which most likely can result in a crash. Remove the asterisk.
  3. The third problem is that you treat the shared memory as both an array of integers (with n) and as a string. You cant really do both, pick one or the other.
  4. You create the shared memory in the parent process, but wait for the child process to finish before you create the memory.
  5. There is a race condition between the parent and child process, since the share memory might be created after the child tries to access it.

Edit I came up with this instead, which seems to work for me. I added comments on the things I changed.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/wait.h>  /* Needed for the wait function */
#include <unistd.h>    /* needed for the fork function */
#include <string.h>    /* needed for the strcat function */
#define SHMSIZE 27
int main() {
   int shmid;
   char *shm;

   if(fork() == 0) {
      shmid = shmget(2009, SHMSIZE, 0);
      shm = shmat(shmid, 0, 0);
      char *s = (char *) shm;
      *s = '\0';  /* Set first location to string terminator, for later append */
      int i;
      for(i=0; i<5; i++) {
         int n;  /* Variable to get the number into */
         printf("Enter number<%i>: ", i);
         scanf("%d", &n);

         char number[20];
         sprintf(number, "%d", n);  /* Convert the number to string */
         strcat(s, number);  /* Append the number to the string */
      }
      strcat(s, "\n");  /* Append newline */
      printf ("Child wrote <%s>\n",shm);
      shmdt(shm);
   }
   else {
      /* Variable s removed, it wasn't used */
      /* Removed first call to wait as it held up parent process */
      shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
      shm = shmat(shmid, 0, 0);
      wait(NULL);
      printf ("Parent reads <%s>\n",shm) ;
      shmdt(shm);
      shmctl(shmid, IPC_RMID, NULL);
   }
   return 0;
}

Do note that point 5 in the list above have not been resolved.

花之痕靓丽 2024-12-23 16:47:51

我的问题太愚蠢了。我需要为子进程提供写入 SHM 的能力。 if 块中的这一行:

shmid = shmget(2009, SHMSIZE, 0);

将变成这样:

shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);

感谢你们所有人,特别是@JoachimPileborg :)

My problem was so stupid. I need to provide the Child process with the ability to write into the SHM. This line in the if-block :

shmid = shmget(2009, SHMSIZE, 0);

Will become like this:

shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);

Thanks to you all and especially to @JoachimPileborg :)

勿忘初心 2024-12-23 16:47:51

您的描述似乎不正确,因为没有输出“Parent Wrote <>”的代码。

您正在读取数字并将它们作为 int 存储在 *n++ 中,但是随后您将 '\n' 字符附加到 n-int 数组中,并且将 shm 视为字符串?

在我看来,在你的孩子身上,你正在创建一个共享内存,写入它,然后关闭(丢弃)共享内存。然后你的第二部分打开一个具有相同段的新共享内存,但它是一个新的共享内存。通常,一个进程创建共享内存,然后第二个进程打开它,当最后一个进程关闭共享内存时,操作系统会释放它。

Your description seems to not be correct since there is no code that outputs "Parent Wrote <>".

You are reading numbers and storing them as int in *n++, but then you are appending a '\n' character to the n-int array and you are treating shm as a string?

It seems to me that in your child you are creating a shared memory, writing to it and then closing (discarding) the shared memory. Then your second part opens a new shared memory with the same segment, but yet it is a new shared memory. Normally one process creates a shared memory, then the second opens it and when the last process closes the shared memory, then it is freed by the OS.

风向决定发型 2024-12-23 16:47:51

一个问题是子进程在父进程创建共享内存之前尝试使用该共享内存。父级在创建共享内存之前有一个 wait() 调用,因此当客户端尝试检索 id 时,它不会存在。即使 wait() 调用被移动,它也可能无法工作,因为存在竞争条件。对 shmget 的调用可能需要在 fork 调用之前进行(或者在子进程中检索它之前使用一些同步来确保它确实存在)。

并且(正如其他人已经指出的那样),孩子试图将整数写入内存,而读取(打印它)则尝试将其视为字符串。

One problem is that the child process is attempting to use get the shared memory before it has been created by the parent. The parent has a wait() call before creating the shared memory, so it won't exist when the client tries to retrieve the id. Even if the wait() call is moved, it may not work because there is a race condition. The call to shmget may need to precede the fork call (or use some synchronization to make sure it actually exists before retrieving it in the child process).

And (as others have already pointed out), the child is attempting to write integers to the memory while the reading (printing of it) tries to treat it as a character string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文