【问题标题】:open() fails at first attemptopen() 首次尝试失败
【发布时间】:2012-02-23 11:22:44
【问题描述】:

open() 在第一次尝试时失败并显示 ENOENT(没有这样的文件或目录),但在随后的尝试中工作正常。
我的程序派生了一个子进程并等待子进程完成使用waitpid()。子进程使用execl()在特定目录中创建从用户接收的文件路径的副本。
一旦子进程退出,父进程使用open() 打开这个新创建的副本。但是,它在第​​一次尝试时失败并显示 ENOENT(没有这样的文件或目录)。我可以看到子进程在指定目录中创建了一个文件。
如果我通过提供相同的文件名再次运行该程序,那么它工作正常。我的问题是:为什么第一次尝试时不打开文件?我需要刷新目录还是它是什么?

我在红帽上

这里有一个快速的 N 脏代码片段

my_function()
{
char *src = "TEST.txt";  
char *dest = "./Output/";  
char *fp = "/Output/TEST.txt";  
int fd;  
struct fstat file_stat;  

pid_t PID = fork();  

if(PID == -1)  
      exit(1);   


if(PID == 0)  
{
       execl("/bin/cp", "/bin/cp", src, dest);   
       exit(1);   
}   


if(PID > 0)  
{  
       int chldstat;
       pid_t ws = waitpid(PID,&chldstat,WNOHANG);  
}  


if(stat(fp,&file_stat) == -1)  
{  
       perror("stat");  
       exit(1);  
}  


if((fd = open(dest,O_RDWR)) == -1)  
{  
       perror("open");
       exit(1);
}  


if((fp=mmap(0,file_stat.st_size,PROT_READ | PROT_WRITE,fd,0)) == -1)  
{  
       perror("mmap");
       exit(1);
}  


//OTHER ROUTINES      
.............  
............    
............  


}  

【问题讨论】:

  • 你能发布一些你的代码吗?
  • 您需要显示代码,尤其是。创建/等待子进程。听起来你等待孩子完成的方式有些古怪。

标签: c linux fork os.execl


【解决方案1】:

如前所述,没有源代码很难回答这样的问题。但是:

您似乎患有竞争状况。该文件已创建,但比您第一次打开尝试晚了一点。在您第二次尝试时,您会更幸运,并且该文件已经创建。
再次运行可以正常运行的事实支持了这一理论 - 该文件甚至在程序启动之前就已经存在,因此可以随时打开它。

你怎么会有比赛条件?如果是孩子创建的,而父亲只有在验证孩子结束后才尝试打开它,那么应该没有问题。
很难推测出了什么问题。也许你等待错误的过程。也许孩子创建了另一个创建文件的进程,而父母只等待第一个孩子。还有一百万个可能。

【讨论】:

    【解决方案2】:

    您正在使用WNOHANG 标志调用waitpid(),这意味着如果它仍在运行,它实际上不会阻塞等待子进程。该标志用于测试子进程状态是否发生了变化,如果没有,则无需实际等待;返回值将指示孩子是否准备好。如果您希望它阻止等待它,请删除 WNOHANG 标志。但是,请注意,如果调用被信号处理程序中断,它仍可能在子状态更改之前返回。如果您不关心孩子是否成功退出,那么您可以这样写:

    while (waitpid(PID, &chldstat, 0) == -1 && errno == EINTR)
        ;
    

    【讨论】:

      猜你喜欢
      • 2017-01-21
      • 2022-01-15
      • 1970-01-01
      • 2021-12-16
      • 2012-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      相关资源
      最近更新 更多