ftw和进程问题

时间:2018-03-08 23:17:08

标签: c linux

  

编写一个使用两个进程(而不是线程)对C进行排序的C程序   目录中的常规文件和基于文件的子目录   大小。该程序产生一个进程(即子进程)进行扫描   常规文件的目录和子目录。当。。。的时候   (子)进程找到一个常规文件,它获取大小,然后发送   通过的父进程的文件大小和路径名   管道或FIFO。父进程排序(按升序排列)和   组织大小和路径名信息。当孩子进程   完成扫描,它通知父进程和父进程   process打印出文件的大小和路径名。

#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/wait.h>

static int dirSize = 0;
char *dirPath = NULL;
static int dirInfo(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf){
    dirSize = sb -> st_size;
    dirPath = fpath;
    return 0;
}

int main(int argc, char *argv[]){
    pid_t processCheck[1];
    int i = 0;
    int pipes[1][2];
    char *directoryPath = argv[1];
    pipe(pipes[i]);
    processCheck[0] = fork();
    if(processCheck[0]==0){
        close(pipes[i][0]);
        nftw(directoryPath, dirInfo, 10, FTW_PHYS);
        write(pipes[i][1], &dirSize, sizeof dirSize);
        write(pipes[i][1], &dirPath, sizeof dirPath);
        close(pipes[i][1]);
        exit(0);
    }
    close(pipes[i][1]);
    int childProcessStatus;
    if(WIFEXITED(childProcessStatus)&&WEXITSTATUS(childProcessStatus)==0){
        int v;
        char * d=NULL;
        if(read(pipes[i][0], &v, sizeof v) == sizeof(v)){
            printf("%d\t" , v);
        }
        if(read(pipes[i][0], &d, sizeof d) == sizeof(d)){
            printf("%s\n", d);
        }
    }
    close(pipes[i][0]);
    return 0;
}

该程序仅打印4096 4096

1 个答案:

答案 0 :(得分:1)

sizeof dirPath返回指针的大小,而不是长度 串。由于readwrite没有消息边界,因为Mark Plotnick指出了这一点 在注释中,您需要声明字符串的修复大小 (意思是父母和孩子使用相同的大小)或孩子写的长度 字符串然后是字符串。我会选择第二个:

对于孩子:

size_t len = strlen(dirPath);

write(pipes[i][1], &dirSize, sizeof dirSize);
write(pipes[i][1], &len, sizeof len);
write(pipes[i][1], dirPath, len); // not &dirPath, otherwise you are sending
                                  // an address, not the string

和父母:

int v;
size_t len;
char *d=NULL;
if(read(pipes[i][0], &v, sizeof v) != sizeof(v))
{
    fprintf(stderr, "Invalid answer from child\n");
    exit(1);
}

if(read(pipes[i][0], &len, sizeof len) != sizeof len)
{
    fprintf(stderr, "Invalid answer from child\n");
    exit(1);
}

// don't have to worry about setting the
// \0-terminating byte
d = calloc(len + 1, 1);

if(d == NULL)
{
    fprintf(stderr, "out of memory\n");
    exit(1);
}

if(read(pipes[i][0], d, len) != len)
{
    fprintf(stderr, "Invalid answer from child\n");
    free(d);
    exit(1);
}

printf("child sent: dirSize = %d\n", v);
printf("child sent: dirPath = %s\n", d);
free(d);
close(pipes[i][0]);

写这个

write(pipes[i][1], &dirPath, sizeof dirPath);

是一个坏主意,您正在发送指针的地址。这个地址最多 可能只在孩子的虚拟空间的记忆中有效,你没有 保证父进程在同一地址具有相同的信息 在父虚拟空间中,父节点可能会尝试访问它的内存 不被允许。您必须发送数组的内容或者如果您愿意 避免这种情况,那么你必须使用共享内存。

最后一件事,你不是wait让孩子结束。你应该这样做:

close(pipes[i][1]);
int childProcessStatus;
waitpid(processCheck[0], &childProcessStatus, 0);

if(WIFEXITED(childProcessStatus)&&WEXITSTATUS(childProcessStatus)==0)
{
    ...
}