我正在尝试在C中使用管道。我有两个在父进程和子进程之间创建两个管道。我必须读取一个4096字节的文件(如果有更少的话,则更小),我必须通过管道读取的数据量和读数的次数。例如,要复制6KB文件,父级会将文件的前4KB数据写入共享内存,并通过管道向子级发送两个整数1和4096。子进程接收这两个数字,从共享内存复制4096个字节到输出文件,并通过另一个管道将1发送回父进程。收到1后,父级将左侧2KB数据复制到共享内存,并将2和2048发送给子级。子进程从管道接收它们,将2048个字节复制到输出文件,并用2回复父进程。父母然后向孩子发送0,0。孩子收到0并回复0然后退出。父母收到0并退出。
目前我的程序适用于少于一个块的文件,但不适用于大于一个块(4096字节)的文件
697,谢谢你的指出,我已经修改了我的程序如下但仍有问题,基本上如何控制流程为父子父母...#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define SIZE 4096
int file_exist (char *filename)
{
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
int main(int argv, char *argc[]) {
/*Check if program is called correctly*/
if(argv != 3) {
printf("Please call program appropriately\n");
exit(EXIT_FAILURE);
}
FILE *r, *w;
void *sharedMem;
int datapipe[2];
int blockpipe[2];
int shm;
char userInput[5];
char *name = "fsuid_cop4610";
if (file_exist (argc[2]))
{
printf("Would you like to overwrite file (yes/no): ");
scanf("%s", userInput);
if(!strcmp(userInput, "yes")) {
printf("Overwriting file...\n");
//fclose(w);
w = fopen(argc[2], "wb");
if(w == NULL) {
perror("Error with write file");
exit(EXIT_FAILURE);
}
}
else if(!strcmp(userInput, "no")) {
printf("Will not overwrite\n");
exit(EXIT_FAILURE);
}
else {
printf("User input not accepted\n");
exit(EXIT_FAILURE);
}
}
/*Check if read file can open*/
r = fopen(argc[1], "rb");
if(r == NULL) {
perror("Error opening read file");
exit(EXIT_FAILURE);
}
fseek(r, 0, SEEK_END); // seek to end of file
int inputlength = ftell(r); // get current file pointer
printf("inputlength is %d\n",inputlength);
int numofblock = inputlength/SIZE + 1;
fseek(r, 0, SEEK_SET); // seek back to beginning of file
/*Check if write file can open*/
if (pipe(datapipe) < 0) {
perror("Pipe");
exit(EXIT_FAILURE);
}
if (pipe(blockpipe) < 0) {
perror("Pipe");
exit(EXIT_FAILURE);
}
/*Check if forking process is successful*/
pid_t pid = fork();
if(pid < 0) {
perror("Fork");
exit(EXIT_FAILURE);
}
shm = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(shm == -1) {
perror("Shared memory");
exit(EXIT_FAILURE);
}
if(ftruncate(shm, SIZE) == -1) {
perror("Shared Memory");
exit(EXIT_FAILURE);
}
sharedMem = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if(sharedMem == MAP_FAILED) {
perror("Mapping shared memory");
exit(EXIT_FAILURE);
}
if (pid>0) { // parent
printf(" parent before close data0,block1\n");
close(datapipe[0]); // close read, will write data
close(blockpipe[1]); // close write, will read block number
printf(" parent close data0,block1\n");
for (int i=1; i<=numofblock; i++)
{
printf("... parent process\n");
int blocknumber=i;
printf("parent read from input file into shared memory\n");
int P2SHM = fread(sharedMem, 1, SIZE, r);
if(P2SHM < 0) {
perror("Could not store to shared memory");
exit(EXIT_FAILURE);
}
//printf("parent shared memory conent: %s\n",(char *)sharedMem);
printf("parent data read %d\n",P2SHM);
if (i==1)
{
printf("i=%d parent write to data pipe\n",i);
if(write(datapipe[1], &P2SHM, sizeof(int)) < 0) {
perror("parent failed to write to pipe bytes");
exit(EXIT_FAILURE);
}
if(write(datapipe[1], &blocknumber, sizeof(int)) < 0) {
perror("parent failed to write to pipe block number");
exit(EXIT_FAILURE);
}
}
printf("parent read from block pipe\n");
int C2P = read(blockpipe[0], &blocknumber, sizeof(int));
if(C2P < 0) {
perror("parent failed to read value from blockpipe");
exit(EXIT_FAILURE);
}
/*else if(C2P == 0) {
printf("End of file reached\n");
}*/
else {
printf("parent block %d Received succesfully\n", blocknumber);
if (i>= 2)
{
printf("i=%d parent write to data pipe\n",i);
//close(datapipe[0]); // close read, will write data
if(write(datapipe[1], &P2SHM, sizeof(int)) < 0) {
perror("parent failed to write to pipe bytes");
exit(EXIT_FAILURE);
}
if(write(datapipe[1], &blocknumber, sizeof(int)) < 0) {
perror("parent failed to write to pipe block number");
exit(EXIT_FAILURE);
}
//close(datapipe[1]);
}
if(C2P == 0) {
printf("parent End of file reached\n");
}
}
} // end for
printf(" parent before close data1,block0\n");
close(datapipe[1]);
close(blockpipe[0]);
printf(" parent close data1,block0\n");
printf(" ... existing parent process\n");
}
else { // pid=0 child
printf(" child before close data1,block0\n");
close(datapipe[1]); // close write, will read data
close(blockpipe[0]); // close read, will write block number
printf(" child close data1,block0\n");
for (int j=1; j<=numofblock; j++)
{
printf(".... child process\n");
int cBytes, len, len2;
int blocknumber = 1;
printf("child read from datapipe\n");
len = read(datapipe[0], &cBytes, sizeof(cBytes));
len2 = read(datapipe[0], &blocknumber, sizeof(blocknumber));
printf("child wrote to blockpipe blocknumber=%d\n", blocknumber);
write(blockpipe[1], &blocknumber, sizeof(blocknumber));
printf("child There are %i bytes\n", cBytes);
if(len >= 0)
{
printf("child writing to file\n");
//fwrite(sharedMem, 1, sizeof(sharedMem), w);
//printf("child shared memory conent: %s\n",(char *)sharedMem);
char* res = (char *)sharedMem;
//printf("res = %s\n",res);
//printf("errno before write=%d",errno);
shm_unlink(name);
//int writtenbyte = fwrite(res, sizeof(char), strlen(res), w);
int writtenbyte = fwrite(res, sizeof(char), cBytes, w);
if(errno == EINTR) {
printf("somewhting wrong");
}
//printf("errno after write=%d",errno);
printf("writtenbyte = %d\n",writtenbyte);
//fclose(w);
//fputs((char *)sharedMem, w);
//fwrite(s->name, sizeof(char), strlen(s->name) + 1, fp);
}
/*else if (len == 0) {
printf("End of fle reached\n");
}*/
else { // len < 0
perror("Failed to read from pipe");
exit(EXIT_FAILURE);
}
} // after for
printf(" child before close data0,block1\n");
close(datapipe[0]);
close(blockpipe[1]);
printf(" child close data0,block1\n");
printf("... exiting Child process\n");
}
//shm_unlink(name);
//fclose(r);
fclose(w);
return 0;
}
结果:
输入长度为4177 关闭data0之前的父级,block1 parent close data0,block1 ......父进程 parent从输入文件读入共享内存 父数据读4096 i = 1父写入数据管道 父节点从块管读取 关闭data1之前的子节点,block0 child close data1,block0 ....儿童过程 孩子从datapipe读取 child写到blockpipe blocknumber = 1 child有4096个字节 孩子写到文件 父块1成功收到 ......父进程 parent从输入文件读入共享内存 父数据读81 父节点从块管读取 父块2成功收到 i = 2父写入数据管道
注意子写入块号为1,但是父节点接收到块号1,然后接收到块号2,并且从父节点开始第二次写入后停止,而不写入输出文件。有什么想法吗?