【发布时间】:2013-10-20 20:42:13
【问题描述】:
我正在使用叉子和管道来查找文件内部字符串中 1 和 0 的数量。但是,我从来没有达到我的程序的正确结束,它计算了 1 和 0。这是一小部分代码,所以这是整个程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
int main (int argc, char** argv)
{
int leftR, rightR;
char *string;
long size;
int recursion = 0;
if (argc == 3)
{
string = argv[1];
size = strlen(string);
printf("the string is %s\n", string);
if (size <= 2)
{
int bitCounter[2];
bitCounter[0] = 0;
bitCounter[1] = 0;
int i;
for (i=0; i < size; i++)
{
if (string[i]=='0')
{
bitCounter[0]++;
}
else
{
bitCounter[1]++;
}
}
write(STDOUT_FILENO, &bitCounter, sizeof(int)*2);
printf("read bits, sending back %d ones and %d zeroes\n", bitCounter[1], bitCounter[0]);
return 0;
}
else
{
recursion = 1;
}
}
if (argc == 2 || recursion)
{
char *data;
if (!recursion)
{
FILE* filePointer;
if ((filePointer = fopen(argv[1], "r")) == NULL)
{
perror("file didn't work");
}
fseek(filePointer, 0, SEEK_END);
size = ftell(filePointer);
fseek(filePointer, 0, SEEK_SET);
data = malloc(size+1);
fread(data, size, 1, filePointer);
fclose(filePointer);
}
else
{
data = malloc(size+1);
data = string;
}
char *right;
char *left = malloc((size/2)+1);
if (size%2 == 0)
{
right = malloc(size/2 + 1);
}
else
{
right = malloc(size/2 + 2);
}
memcpy(left, data, size/2);
if (size%2 == 0)
{
memcpy(right, (size/2) + data, size/2);
}
else
{
memcpy(right, (size/2) + data, (size/2) + 1);
}
int pidLeft, pidRight;
int leftPipe[2];
int rightPipe[2];
pipe(leftPipe);
pipe(rightPipe);
fd_set readF;
FD_ZERO(&readF);
FD_SET(leftPipe[0], &readF);
FD_SET(rightPipe[0], &readF);
pidLeft = fork();
if (pidLeft > 0)
{
pidRight = fork();
if (pidRight > 0)
{
struct timeval timer;
timer.tv_sec = 3;
timer.tv_usec = 0;
close(rightPipe[1]);
close(leftPipe[1]);
dup2(leftPipe[0], STDOUT_FILENO);
dup2(rightPipe[0], STDOUT_FILENO);
select(2, &readF, NULL, NULL, &timer);
read(leftPipe[0], &leftR, sizeof(int)*2);
read(rightPipe[0], &rightR, sizeof(int)*2);
printf("going back to parent.\n");
}
else if (pidRight == 0)
{
close(rightPipe[0]);
execl("my_program", "my_program", right, "y", NULL);
printf("recursion start\n");
exit(1);
}
}
else if (pidLeft == 0)
{
close(leftPipe[0]);
execl("my_program", "my_program", left, "y", NULL);
printf("start recursion LEFT\n");
exit(1);
}
else
{
fprintf(stderr, "something went wrong! No fork!\n");
}
}
else
{
fprintf(stderr, "Please input file name properly\n");
exit(1);
}
int zeroes = leftR + rightR;
int* numOnes[2];
numOnes[0] = &leftR + sizeof(int);
numOnes[1] = &rightR + sizeof(int);
int ones = (int) *numOnes[0] + (int) *numOnes[1];
printf("0's: %d\n1's: %d\n", zeroes, ones);
return 0;
}
但是,输出永远不会达到我想要的结果,将所有内容加起来:
the string is 01010▒z
the string is 010
the string is 0
read bits, sending back 0 ones and 1 zeroes
the string is 10▒z
the string is 10
read bits, sending back 1 ones and 1 zeroes
the string is ▒z
read bits, sending back 2 ones and 0 zeroes
the string is 10
read bits, sending back 1 ones and 1 zeroes
the string is 10100
z
the string is 101
the string is 1
read bits, sending back 1 ones and 0 zeroes
the string is 01
read bits, sending back 1 ones and 1 zeroes
the string is 00
z
the string is 00
read bits, sending back 0 ones and 2 zeroes
the string is
z
read bits, sending back 2 ones and 0 zeroes
(140) Admin $
几个要点让你更容易理解代码:
- argc 在子进程中执行时只有 3
- children 只会读取小于等于 2 的字符串,否则递归地再次将字符串切成两半(并产生更多的孩子)
- 父母生一个左右孩子,都拿一半的弦来处理
我想有几个简单的问题可以开始:
- 我是否正确使用了 select() 和 execl()?
- 我是否正确使用了 read() 和 write()?
- 我缺少的主要进程中是否有出口?
- 两个孩子都在正确工作和使用管道吗?
- (不太重要)字符串中的奇怪字符是否会影响我的计数?那是我的字符串中的一个空终止符吗?
【问题讨论】:
-
请发布编译无错误的代码:
int zeroes = *leftR + *rightR;会产生错误,因为leftR和rightR都不是指针。下一行也有类似的抱怨。 -
已修复,对此感到抱歉。
-
“固定”也许不是我会使用的术语。这段代码:
int rights = (int) &rightR; int lefts = (int) &leftR; int zeroes = lefts + rights; int ones = (int)(&leftR + sizeof(int)) + (int)(&rightR + sizeof(int));非同寻常——而且极不可能是正确的。将两个地址加在一起会产生垃圾,而不是答案。我不确定你认为(&leftR + sizeof(int))会产生什么,但它不是“定义的行为”。 -
另外,鉴于
leftR和rightR都是单个整数,代码read(leftPipe[0], &leftR, sizeof(int)*2); read(rightPipe[0], &rightR, sizeof(int)*2);将两个int值读取到每个单个整数中保证是未定义的行为。跨度> -
是的,绝对是这样。主要问题是我的程序甚至没有到达最后一个区域,我什至无法正确调试它。本质上,
(&leftR + sizeof(int))应该从从左孩子传递的数组bitCounter中取出下一个元素。无论如何,我做了一些改变,希望能避免未定义的行为。
标签: c multithreading select fork pipe