如何解决无法从 C 管道读取多个结构类型消息
我正在尝试开发一个程序,该程序将启动 2 个子进程来运行,这些子进程将读取一个目录中的所有文件并将信息传递给另一个子进程以在另一个目录中创建这些文件。 下面是我的代码。但是我无法从管道中读取消息。如果我传递一个硬编码的字符串对象,我就可以从管道中读取它。但不是我试图传递的结构对象。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#define BUF_SIZE 1024
// Struct to store the file name and content
struct FileDetails{
char *file_name;
char *file_content;
};
// Helper function to create file at a given path and with given content.
void * createFile(struct FileDetails fileDetail){
int status;
FILE *fptr;
fptr = fopen(fileDetail.file_name,"a");
if(fptr == NULL)
{
perror("Error!");
return NULL;
}
fprintf(fptr,"%s",fileDetail.file_content);
fclose(fptr);
return NULL;
}
//Helper function used to copy two strings into one and return new string
char* strAppend(char* str1,char* str2){
char * new_str ;
if((new_str = malloc(strlen(str1)+strlen(str2)+1)) != NULL){
new_str[0] = '\0'; // ensures the memory is an empty string
strcat(new_str,str1);
strcat(new_str,str2);
} else {
printf("%s","malloc Failed!\n");
// exit?
}
return new_str;
}
// Each child will execute this helper funtion. It takes one argument which is the location of the directory to read all files from and send data to other child.
// Second argument is the pipe where we write
void *threadUtility(void *vargp,int* fd1)
{
// Store directory pointer
DIR* directoryPtr;
// Store file pointer
FILE *entry_file;
struct dirent *current_file;
int i;
char* directory = (char *)vargp;
printf("Process started for directory: %s\n",directory);
directoryPtr = opendir(directory);
if(directoryPtr==NULL) {
printf("Error! Unable to read directory: %s\n",directory);
exit(1);
}
close(fd1[0]); // Close reading end of first pipe
while((current_file=readdir(directoryPtr)) != NULL) {
if (!strcmp (current_file->d_name,"."))
continue;
if (!strcmp (current_file->d_name,".."))
continue;
struct FileDetails fileDetail;
fileDetail.file_name = malloc(strlen(current_file->d_name) + 1);
fileDetail.file_name = current_file->d_name;
// Appending directory path to file name to read contents
char * new_str = strAppend(directory,current_file->d_name);
//printf("FileName FQN: %s\n",fileDetail.file_name);
entry_file = fopen(new_str,"r");
struct stat sb;
stat(new_str,&sb);
char *file_contents = malloc(sb.st_size);
fileDetail.file_content = malloc(sb.st_size);
if (entry_file != NULL) {
//Looping through each line of file to read all lines.
while (fscanf(entry_file,"%[^\n] ",file_contents) != EOF) {
fileDetail.file_content = strAppend(fileDetail.file_content,file_contents) ;
fileDetail.file_content = strAppend(fileDetail.file_content,"/n") ;
}
} else{
perror("Failed: ");
exit(1);
}
fclose(entry_file);
//printf("Writing to pipe: %s\n",fileDetail.file_name);
if (write(fd1[1],&fileDetail,sizeof(struct FileDetails)) < 0) {
printf("error writing");
}
}
close(fd1[1]);
closedir(directoryPtr);
printf("Process ended for directory: %s\n",directory);
return NULL;
}
// This program takes two command line argument which are direectory paths of two location.
int main( int argc,char *argv[] )
{
// If 2 paths not provided the program will terminate
if( argc != 3 ) {
printf("Provide two directory paths: %i\n",argc);
exit(1);
}
//Pipes for communication
int fd1[2]; // Used to store two ends of first pipe
int fd2[2]; // Used to store two ends of second pipe
//Create pipes
if (pipe(fd1)==-1)
{
fprintf(stderr,"Pipe Failed" );
return 1;
}
if (pipe(fd2)==-1)
{
fprintf(stderr,"Pipe Failed" );
return 1;
}
// Process ids for two child processes
pid_t dir_one_child_process,dir_two_child_process;
dir_one_child_process = fork();
if (dir_one_child_process == 0) {
/* Child One Process */
threadUtility(strAppend(argv[1],"/"),fd1);
wait(NULL);
// Reading messages sent by 2nd child
close(fd2[1]); // Close writing end of second pip
// Read string from child,print it and close
// reading end.
struct FileDetails readForSecond;
int n_bytes;
while (read(fd2[0],&readForSecond,sizeof(&readForSecond)) > 0) {
printf("From Child One: %s\n",readForSecond.file_name);
// Here you have to call the createFile function in order to create the file once you get the FileDetail object
//I'm stuck here
//sleep(1);
}
printf("From Child Two: %s\n",readForSecond.file_name);
close(fd2[0]);
} else {
dir_two_child_process = fork();
if (dir_two_child_process == 0) {
/* Child Two Process */
close(fd1[1]); // Close writing end of first pipe
struct FileDetails readForFirst;
int n_bytes;
while (read(fd1[0],&readForFirst,sizeof(&readForFirst)) > 0) {
printf("From Child One file_name: %s\n",readForFirst.file_name);
// Here you have to call the createFile function in order to create the file once you get the FileDetail object
//I'm stuck here
//sleep(1);
}
printf("reading ends:");
// Close both reading ends
close(fd1[0]);
threadUtility(strAppend(argv[2],fd2);
} else {
/* Parent Code waiting for two childs to end*/
waitpid(dir_one_child_process,NULL,0);
waitpid(dir_two_child_process,0);
printf("Main Function Ends. Exiting\n");
}
}
exit(0);
}
解决方法
这是一个错误:
write(fd1[1],&fileDetail,sizeof(struct FileDetails))
sizeof(struct FileDetails)
是不是您使用 fileDetail
中的指针存储的数据的大小。由于 struct FileDetails
是
struct FileDetails{
char *file_name;
char *file_content;
};
它只是两个指针的大小(通常是 2x4 或 2x8)。
您可以使用以下方法检查尺寸:
printf("%zu\n",sizeof(struct FileDetails));
所以看起来好像你发送了两个指针值而不是文件的内容。那不是你想要的。
此外,这是错误的:
read(fd2[0],&readForSecond,sizeof(&readForSecond))
^^^^^^^^^^^^^^^^^^^^^
This is size-of a single pointer
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。