Linux的文件奇怪的行为读书 [英] Linux reading from file strange behaviour

查看:171
本文介绍了Linux的文件奇怪的行为读书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我努力使创建一个文件,写0到它,然后使用一个子进程的程序,即交替该值的增量。例如,孩子应该值递增1,并且将其写回到该文件。在此之后,母体它增加为2,并在该文件中写入它。子为3,依此类推。进程之间的同步是通过信号完成。这里是源$ C ​​$ C:

I'm trying to make a program that creates a file, writes 0 into it and then, using a child process, alternates the incrementation of that that value. For example, the child should increment that value to 1, and writes it back to the file. After this, the parent increments it to 2 and writes it in the file. The child to 3, and so on. Synchronization between the processes is done via signals. Here is the source code:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

void sig_hand (int sig);

int fd;

int main()
{
    pid_t pid;
    int i;
    fd = open ("abc.txt",O_RDWR|O_TRUNC);
    if (fd == -1)
    {
        fd = creat ("abc.txt",S_IRUSR|S_IWUSR);
    }
    write (fd,"0",2);
    if ((pid = fork()) < 0)
    {
        fprintf (stderr, "Error creating process\n");
        exit (1);
    } else
    {
        if (pid == 0)
        {
            signal (SIGUSR1,sig_hand);
            for (;;)
            {
                pause();
                kill (getppid(),SIGUSR1);
            }
        }
        if (pid > 0)
        {
            sleep (1);
            signal (SIGUSR1,sig_hand);
            for (i=0;i<5;i++)
            {
                kill (pid,SIGUSR1);
                pause ();
            }
            kill (pid,SIGTERM);
        }
    }
    return 0;
}

void sig_hand (int sig)
{
    int x;
    char c;
    read (fd,&c,2);
    x=atoi(&c);
    x++;
    printf ("x=%d\n",x);
    snprintf (&c,3,"%d",x);
    lseek (fd,0,SEEK_SET);
    printf ("PID %d is writing\n",getpid());
    write (fd,&c,2);
}

运行这个程序产生的输出如下:

Running this program produces the following output:

x=1
PID 4434 is writing
x=1
PID 4433 is writing
x=2
PID 4434 is writing
x=2
PID 4433 is writing
x=3
PID 4434 is writing
x=3
PID 4433 is writing
x=4
PID 4434 is writing
x=4
PID 4433 is writing
x=5
PID 4434 is writing
x=5
PID 4433 is writing

为什么孩子和家长递增相同的值在一次迭代?

Why is the child and the parent incrementing the same value in one iteration?

谢谢!

推荐答案

您的主要问题是,你不能一次这样的信号。你的程序僵持第一,我每次运行它​​。一个程序可以(而且经常会)发送信号之前,另一种是在一个位置,等待它。你是完全依赖于调度程序,你不能预见或predict它。所以,正确的步骤是阻断信号,因此不传递,直到你准备好对付它。下面使用该节目 sigrocmask sigsuspend 来实现这一目标。

Your primary problem is that you can't time the signals that way. Your program deadlocked the first and every time I ran it. One program can (and often will) send the signal before the other is in a position to wait for it. You are completely dependent on the scheduler and you can't anticipate or predict it. So the proper procedure is to block the signal so it isn't delivered until you are ready to deal with it. The program below uses sigrocmask and sigsuspend to accomplish that.

您第二个问题是一个克里斯J. Kiick在的感动。你读,并从1个字节的内存位置写2个字节但是,更重要的是,文件描述符家长和孩子之间的共享,所以你需要在每个时间或其他程序以寻求适当的位置会离开它放到你间没有'T期待的。

Your second problem is the one Chris J. Kiick touched upon. You were reading and writing 2 bytes from a 1 byte memory location But, more importantly, the file descriptor is shared between the parent and the child so you need to seek to the proper position each time or the other process will leave it somewhere you weren't expecting.

#define _POSIX_C_SOURCE 1

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

void sig_hand(int sig);

int fd;

int main()
{
    pid_t pid;
    int i;

    if ((fd = open("abc.txt", O_RDWR | O_TRUNC)) == -1)
        errExit("open");

    struct sigaction sa;
    sigset_t saveMask, blockMask;

    //block SIGUSR1
    sigemptyset(&blockMask);
    sigaddset(&blockMask, SIGUSR1);

    if (sigprocmask(SIG_BLOCK, &blockMask, &saveMask) == -1)
        errExit("sigprocmask");

    //set up signal handler (both parent & child)
    sigemptyset(&sa.sa_mask);

    sa.sa_flags = 0;
    sa.sa_handler = sig_hand;

    if (sigaction(SIGUSR1, &sa, NULL) == -1)
        errExit("sigaction");

    if (write (fd, "\0", sizeof(char)) == -1)
        errExit("initial write");

    if ((pid = fork()) < 0)
        errExit("fork");

    if (pid == 0)
    {
        for (;;)
        {
            if (sigsuspend(&saveMask) == -1 && errno != EINTR)
                errExit("sigsuspend");

            kill(getppid(), SIGUSR1);
        }
    }

    if (pid > 0)
    {
        for (i = 0;i < 5;i++)
        {
            kill(pid, SIGUSR1);

            if (sigsuspend(&saveMask) == -1 && errno != EINTR)
                errExit("sigsuspend");
        }

        kill(pid, SIGTERM);
    }

    return 0;
}


void sig_hand(int sig)
{
    char c;

    if (lseek(fd, 0, SEEK_SET) == (off_t) - 1)
        errExit("lseek");

    if (read(fd, &c, sizeof(char)) == -1)
        errExit("read");

    c++;

    printf("c = %d\n", c);

    if (lseek(fd, 0, SEEK_SET) == (off_t) - 1)
        errExit("lseek");

    printf("PID %d is writing\n", getpid());

    if (write (fd, &c, sizeof(char)) == -1)
        errExit("write");
}

这篇关于Linux的文件奇怪的行为读书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆