使用dup2()写入文件后如何清理文件描述符?

问题描述 投票:0回答:1

我想编写一个程序,将终端传递的参数写入两个名为(fichier,copie)的文件中。

First,两个文件中参数的顺序相同,以及终端使用每个参数的子进程在终端中提供的顺序。

第二,两个文件中的参数顺序相同,即使它与终端中提供的参数顺序不同。

我已经使用“锁定”编写了以下代码,以便在两个文件(fichier,copie)中写入每个参数,但是似乎我无法在两个文件中都写入参数。由于dup2()函数,我将所有参数写入第二个文件(copie)中(我认为文件描述符有问题)。

[如果有人能向我解释我如何清除文件描述符并使参数写入两个文件中,我将感到非常高兴。

[Command: ./try hello haha​​ hene

[[输出:在“ copie”文件中,但“ fichier”文件为空

  1. 88961 ecrit哈哈
  2. 88961 ecrit哈哈
  3. 88962 ecrit hene
  4. 88962 ecrit hene
  5. 88960 ecrit你好
  6. 88960 ecrit你好
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void fils(char *chaine){
    int fic1 = open("fichier", O_CREAT|O_APPEND|O_WRONLY,S_IRUSR|S_IWUSR);
    lseek(fic1 ,0 ,SEEK_SET);
    lockf(fic1 ,F_LOCK,0);
    dup2(fic1, 1);

    printf("%d a ecrit %s\n",getpid(),chaine);
    lseek(fic1 ,0 ,SEEK_SET);
    lockf(fic1 ,F_ULOCK,0);

    int fic2 = open("copie", O_CREAT|O_APPEND|O_WRONLY,S_IRUSR|S_IWUSR);
    lseek(fic2 ,0 ,SEEK_SET);
    lockf(fic2 ,F_LOCK,0);
    dup2(fic2, 1);
    printf("%d a ecrit %s\n",getpid(),chaine);

    int attente=rand()%2;
    fprintf(stderr,"%d attente de %d dans fichier et copie\n",getpid(),attente);
    sleep(attente);

    lseek(fic2 ,0 ,SEEK_SET);
    lockf(fic2 ,F_ULOCK,0);
    close(fic1);
    close(fic2);

    exit(EXIT_SUCCESS);
}

int main(int argc,char **argv){

    int i;
    pid_t pid;
    system("rm -f fichier copie");

    for(i=1;i<argc;i++){
        if((pid=fork())<0){
            printf("Erreur fork\n");
            exit(EXIT_FAILURE);
        }else if(pid==0){
            fils(argv[i]);
        }
    }
    exit(EXIT_SUCCESS);
}
c process locking fork ipc
1个回答
0
投票

没有任何内容写入fichier,因为您没有使用fflush(stdout),并且在切换标准输出以写入copie之前缓冲区未满。

lseek()调用几乎没有意义;由于O_APPEND,写入将在文件末尾进行。它们背后的逻辑是确保整个文件都被锁定,但是…

lockf()调用没有意义; O_APPEND标志可确保在文件末尾进行写入,并且磁盘文件不会错开单独进程中单独并发写入调用的内容。

将它们放在一起,以及等待子进程死亡的循环,会导致:

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

static void fils(char *chaine)
{
    int fic1 = open("fichier", O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
    dup2(fic1, 1);
    close(fic1);

    printf("%d a ecrit %s\n", (int)getpid(), chaine);
    fflush(stdout);

    int fic2 = open("copie", O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
    dup2(fic2, 1);
    close(fic2);
    printf("%d a ecrit %s\n", (int)getpid(), chaine);
    fflush(stdout);

    int attente = rand() % 2;
    fprintf(stderr, "%d attente de %d dans fichier et copie\n", (int)getpid(), attente);
    sleep(attente);

    exit(EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
    int i;
    pid_t pid;

    remove("fichier");
    remove("copie");

    for (i = 1; i < argc; i++)
    {
        if ((pid = fork()) < 0)
        {
            fprintf(stderr, "Erreur fork\n");
            exit(EXIT_FAILURE);
        }
        else if (pid == 0)
        {
            fils(argv[i]);
        }
    }

    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
    {
        printf("%d: child %d exited with status 0x%.4X\n",
               (int)getpid(), corpse, status);
    }
    return(EXIT_SUCCESS);
}

当我运行它时,我得到了输出:

$ open29 hello haha hene
95396 attente de 1 dans fichier et copie
95395 attente de 1 dans fichier et copie
95397 attente de 1 dans fichier et copie
95394: child 95397 exited with status 0x0000
95394: child 95396 exited with status 0x0000
95394: child 95395 exited with status 0x0000
$ cat fichier
95395 a ecrit hello
95396 a ecrit haha
95397 a ecrit hene
$ cat copie
95396 a ecrit haha
95395 a ecrit hello
95397 a ecrit hene
$

请注意,所有孩子都睡了相同的时间。使用srand()进行播种时要注意在不同的子代中具有不同的序列(例如,在每个子代中,在srand(getpid())的顶部调用fils())。

我也确实运行了您的代码版本,该代码保留了您的锁定方案,但在调用fflush(stdout)之后使用了printf()。输出没有实质性的不同。文件fichier包含带有hellohenehaha的行;文件copie包含带有hellohahahene的行。关键的变化是使用fflush(stdout);来获取写入到fichiercopie的数据。

© www.soinside.com 2019 - 2024. All rights reserved.