c - 使用 dup2() 写入文件后如何清理文件描述符?
问题描述
我想编写一个程序,将终端传递的参数写入两个名为(fichier,copie)的文件。
首先,两个文件中的参数顺序相同,以及在终端中为每个参数使用子进程提供的顺序。
其次,两个文件中的参数顺序相同,尽管它与终端中提供的参数顺序不同。
我已经使用“锁定”编写了下面的代码,以便在两个文件(fichier,副本)中写入每个参数,但似乎我无法在两个文件中写入参数。由于 dup2() 函数,我将所有参数写入第二个文件(副本)(我认为我的文件描述符有问题)。
如果有人可以向我解释如何清除文件描述符并将参数写入两个文件,我将非常高兴。
命令: ./try hello haha hene
输出:在“副本”文件中,但“fichier”文件为空
- 88961 一个暴躁哈哈
- 88961 一个暴躁哈哈
- 88962 一个 ecrit hene
- 88962 一个 ecrit hene
- 88960 一个 ecrit 你好
- 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);
}
解决方案
没有写入任何内容,因为在您将标准输出切换为写入之前,您fichier
不使用并且缓冲区未满。fflush(stdout)
copie
这些lseek()
电话大多毫无意义。写入将发生在文件末尾,因为O_APPEND
. 它们背后的逻辑是确保整个文件被锁定,但是……</p>
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
包含带有hello
, hene
, haha
;的行 该文件copie
包含带有hello
, haha
,的行hene
。关键的变化是使用fflush(stdout);
来获取写入的数据fichier
以及copie
.
推荐阅读
- android - 数据未显示在 recyclerview 上 - 出现错误未附加布局管理器;跳过布局
- java - Maven - 尝试构建项目时出错
- php - 在 php 中获取 XML 提要
- android - 缩放 X 轴 MPAndroidCharts
- ios - Facebook App Review iOS - 无法选择“从 Apple App Store 下载”
- css - 将按钮组与 div 内的右端对齐
- r - 我的 R 函数的奇怪输出
- dynamics-crm - 带有 WordTemplateExportRecordId 的 MS CRM Word 文档生成:
- oracle - 如何从我的 oracle pl sql 程序运行 bat 文件
- mongodb - MongoDB 分组和项目自定义字段