我正在使用forks和pipe来查找文件中字符串中的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 $
快速了解一下代码更容易理解:
我想一些简单的问题可以开始:
答案 0 :(得分:1)
这是一个更难解决的问题。代码正在做一个模糊的工作,写得相当模糊。据我所知,它应该被称为my_program
,并且应该以文件名作为单个参数调用。然后,该进程将打开该文件,将其内容读入两个数组(left
和right
),而无需确保它们是字符串(无空终止)。然后该过程分叉两次。然后用一个left
(非)字符串作为参数并且它是left
的信息来执行自己,并且使用right
(非)字符串作为参数执行自己以及它是正确的信息。由于没有很好的理由,父进程与select()
混淆,并且没有检查返回值。然后调用read来获取有关两个管道的信息。这些读取将阻塞,直到数据准备就绪,因此select()
实际上根本没有帮助。 (我仍然试图确定递归位适合的位置。)此外,大多数系统调用都没有进行错误检查。
然而,考虑到大纲操作(读取文件,拆分,儿童执行,并执行一半并报告),我会写这样的事情:
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void err_exit(char const *fmt, ...);
int main(int argc, char * *argv)
{
int l_data[2] = { -1, -1 };
int r_data[2] = { -1, -1 };
char *string;
size_t size;
char *arg0 = argv[0];
if (argc != 2 && argc != 3)
err_exit("Usage: %s file\n", argv[0]);
if (argc == 3)
{
/* Child process */
string = argv[1];
size = strlen(string);
fprintf(stderr, "%d: the string is %s\n", (int)getpid(), string);
if (size <= 2)
{
int bitCounter[2];
bitCounter[0] = 0;
bitCounter[1] = 0;
for (size_t i = 0; i < size; i++)
{
if (string[i] == '0')
bitCounter[0]++;
else if (string[i] == '1')
bitCounter[1]++;
}
if (write(STDOUT_FILENO, bitCounter, sizeof(int)*2) != sizeof(int)*2)
err_exit("%d: failed to write on standard output\n",
(int)getpid());
fprintf(stderr, "%d: read bits, sending back %d ones and %d zeroes\n",
(int)getpid(), bitCounter[1], bitCounter[0]);
exit(0);
}
fprintf(stderr, "%d: doing recursion - string too big (%zu)\n",
(int)getpid(), size);
}
char *data = string;
if (argc == 2)
{
FILE *filePointer;
if ((filePointer = fopen(argv[1], "r")) == NULL)
{
perror("file didn't work");
exit(1);
}
fseek(filePointer, 0, SEEK_END);
size = ftell(filePointer);
fseek(filePointer, 0, SEEK_SET);
data = malloc(size+1);
fread(data, size, 1, filePointer);
data[size] = '\0';
if (data[size-1] == '\n')
data[--size] = '\0';
fclose(filePointer);
fprintf(stderr, "%d: data <<%s>>\n", (int)getpid(), data);
}
size_t l_size = size/2;
size_t r_size = size - l_size;
char *left = malloc(l_size+1);
char *right = malloc(r_size+1);
memcpy(left, data, l_size);
left[l_size] = '\0';
memcpy(right, data + l_size, r_size);
right[r_size] = '\0';
int l_pid, r_pid;
int l_pipe[2] = { -1, -1 };
int r_pipe[2] = { -1, -1 };
if (pipe(l_pipe) != 0 || pipe(r_pipe) != 0)
err_exit("%d: Failed to create pipes\n", (int)getpid());
fprintf(stderr, "%d: forking (l_size = %zu, r_size = %zu)\n",
(int)getpid(), l_size, r_size);
l_pid = fork();
if (l_pid < 0)
err_exit("%d: Failed to fork() left child\n", (int)getpid());
else if (l_pid == 0)
{
dup2(l_pipe[1], STDOUT_FILENO);
close(l_pipe[0]);
close(l_pipe[1]);
close(r_pipe[0]);
close(r_pipe[1]);
fprintf(stderr, "%d: left execing with string <<%s>>\n", (int)getpid(), left);
execl(arg0, arg0, left, "y", NULL);
err_exit("%d: failed to start recursion LEFT\n", (int)getpid());
}
else if ((r_pid = fork()) < 0)
err_exit("%d: Failed to fork() right child\n", (int)getpid());
else if (r_pid == 0)
{
dup2(r_pipe[1], STDOUT_FILENO);
close(l_pipe[0]);
close(l_pipe[1]);
close(r_pipe[0]);
close(r_pipe[1]);
fprintf(stderr, "%d: right execing with string <<%s>>\n", (int)getpid(), right);
execl(arg0, arg0, right, "y", NULL);
err_exit("%d: failed to start recursion RIGHT\n", (int)getpid());
}
else
{
/* Parent process */
int nbytes;
close(r_pipe[1]);
close(l_pipe[1]);
if ((nbytes = read(l_pipe[0], l_data, sizeof(int)*2)) != sizeof(int)*2)
err_exit("%d: Read left pipe failed (%d)\n", (int)getpid(), nbytes);
if ((nbytes = read(r_pipe[0], r_data, sizeof(int)*2)) != sizeof(int)*2)
err_exit("%d: Read right pipe failed (%d)\n", (int)getpid(), nbytes);
close(l_pipe[0]);
close(r_pipe[0]);
}
int zeroes = l_data[0] + r_data[0];
int ones = l_data[1] + r_data[1];
if (argc == 3)
{
int data[2] = { zeroes, ones };
if (write(STDOUT_FILENO, data, sizeof(data)) != sizeof(data))
err_exit("%d: failed to read binary data from stdin\n", (int)getpid());
fprintf(stderr, "%d: binary write to stdout OK\n", (int)getpid());
}
fprintf(stderr, "%d: 0's = %d, 1's = %d\n", (int)getpid(), zeroes, ones);
return 0;
}
static void err_exit(char const *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
exit(1);
}
给定一个输入文件:
0101010111111
输出是:
11070: data <<0101010111111>>
11070: forking (l_size = 6, r_size = 7)
11073: right execing with string <<0111111>>
11072: left execing with string <<010101>>
11072: the string is 010101
11072: doing recursion - string too big (6)
11072: forking (l_size = 3, r_size = 3)
11073: the string is 0111111
11073: doing recursion - string too big (7)
11073: forking (l_size = 3, r_size = 4)
11074: left execing with string <<010>>
11075: right execing with string <<101>>
11076: left execing with string <<011>>
11077: right execing with string <<1111>>
11074: the string is 010
11074: doing recursion - string too big (3)
11074: forking (l_size = 1, r_size = 2)
11078: left execing with string <<0>>
11076: the string is 011
11076: doing recursion - string too big (3)
11076: forking (l_size = 1, r_size = 2)
11079: right execing with string <<10>>
11075: the string is 101
11075: doing recursion - string too big (3)
11075: forking (l_size = 1, r_size = 2)
11080: left execing with string <<0>>
11077: the string is 1111
11077: doing recursion - string too big (4)
11077: forking (l_size = 2, r_size = 2)
11082: right execing with string <<11>>
11081: left execing with string <<1>>
11083: right execing with string <<01>>
11084: left execing with string <<11>>
11085: right execing with string <<11>>
11079: the string is 10
11078: the string is 0
11079: read bits, sending back 1 ones and 1 zeroes
11078: read bits, sending back 0 ones and 1 zeroes
11074: binary write to stdout OK
11074: 0's = 2, 1's = 1
11082: the string is 11
11082: read bits, sending back 2 ones and 0 zeroes
11080: the string is 0
11080: read bits, sending back 0 ones and 1 zeroes
11076: binary write to stdout OK
11076: 0's = 1, 1's = 2
11081: the string is 1
11081: read bits, sending back 1 ones and 0 zeroes
11084: the string is 11
11084: read bits, sending back 2 ones and 0 zeroes
11083: the string is 01
11083: read bits, sending back 1 ones and 1 zeroes
11075: binary write to stdout OK
11075: 0's = 1, 1's = 2
11072: binary write to stdout OK
11072: 0's = 3, 1's = 3
11085: the string is 11
11085: read bits, sending back 2 ones and 0 zeroes
11077: binary write to stdout OK
11077: 0's = 0, 1's = 4
11073: binary write to stdout OK
11073: 0's = 1, 1's = 6
11070: 0's = 4, 1's = 9