简体   繁体   English

Unix 系统调用:读/写和缓冲区

[英]Unix system calls : read/write and the buffer

I am writing a pretty simple script.我正在编写一个非常简单的脚本。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>


int main(){
        int pipefd[2];
        pid_t c;
        int value[2];
        c = fork();
        if(c<0){
                perror("in fork");
                exit(1);
        }
        if(c==0){
                printf("i am the child\n");
                int buf[2];
                buf[0]=3;
                buf[1]=0;
                write(pipefd[1], buf, 4);
                write(pipefd[1],buf+1,4);
                close(pipefd[1]);
                exit(0);
        }
          if (pipe(pipefd) == -1) {      /*UPDATE */
                        perror("pipe");   
                        exit(EXIT_FAILURE);
          }

        read(pipefd[0], value, 4);
        read(pipefd[0], value+1, 4);
        close(pipefd[0]);
        printf("%d %d\n", value[0], value[1]);
        exit(0);
}

What I intend to do is to achieve:我打算做的是实现:

value[0] = buf[0];值[0] = buf[0]; value[1] = buf[1];值[1] = buf[1];

( and print those of course). (当然打印出来)。

But all I get as a result is:但我得到的结果是:

-1299582208 32766
i am the child

Because, I have ints, I assumed that each will hold 4 bytes.因为,我有整数,我假设每个整数都包含 4 个字节。 And I think that for an int array each element will holds 4 bytes.而且我认为对于一个 int 数组,每个元素将包含 4 个字节。 But clearly I am missing something.但显然我错过了一些东西。 Any help?有什么帮助吗?

As I mentioned in my top comment: Where is the pipe syscall?正如我在顶级评论中提到的: pipe系统调用在哪里?

Without it, the write and read calls will probably fail because pipefd has random values.没有它, writeread调用可能会失败,因为pipefd具有随机值。

So, the parent will never have value filled in correctly.因此,父母永远不会正确填写value

Because these [unitialized] values are on the stack, they will have random values, which is what you're seeing.因为这些 [未初始化] 值在堆栈上,它们将具有随机值,这就是您所看到的。

This is UB [undefined behavior].这是 UB [未定义行为]。

Different systems/compilers may manipulate the stack differently, which is why you see different [yet still random] results on different configurations.不同的系统/编译器可能会以不同的方式操作堆栈,这就是为什么您会在不同的配置上看到不同的[但仍然是随机的] 结果。

To fix, add the following above your fork call:要修复,请在您的fork调用上方添加以下内容:

pipe(pipefd);

I downloaded, built, and ran your program.我下载、构建并运行了你的程序。 Before I added the fix, I got random values.在我添加修复之前,我得到了随机值。 After applying the fix, I get 3 0 as the output, which is what you expected/wanted.应用修复后,我得到3 0作为 output,这是您所期望/想要的。

Note: As others have mentioned, you could check the return codes for read and write .注意:正如其他人所提到的,您可以检查readwrite的返回码。 If you had, they might return -1 and put an error code in errno that would have helped you debug the issue.如果你有,他们可能会返回-1并在errno中放置一个错误代码,这将有助于你调试问题。

A very simple fix would be to put a sleep(1) call right above your read() calls - obviously this isn't a great solution.一个非常简单的解决方法是在您的read()调用之上放置一个sleep(1)调用 - 显然这不是一个很好的解决方案。

An important early lesson in multi process programming and communications is "race conditions".多进程编程和通信的一个重要早期教训是“竞争条件”。 Your fork'd child is executing before the parent, it seems.看来,您的分叉子项在父项之前执行。 I bet if you ran this 20 times, you might get X number of times where it does what you want!我敢打赌,如果你跑了 20 次,你可能会得到 X 次它做你想做的事!

You cannot guarantee the order of execution.您不能保证执行的顺序。 So a sleep(1) will suffice until you learn more advanced techniques on resource locking (mutexes, semaphores).因此,在您学习更高级的资源锁定技术(互斥锁、信号量)之前,sleep(1) 就足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM