这是我想要做的:
编写一个带有整数命令行参数n的C程序,生成n个进程,每个进程生成-100到100之间的随机数,然后计算并打印出这些随机数的总和。 每个进程都需要打印出它生成的随机数。
这是我到目前为止:
#include #include #include #include #include #include #include int main(int argc, char *argv[]){ int command,processCheck; // processCheck: to check if fork was successful or not and to char * strNumProcess = NULL;// check the status of child process while((command = getopt(argc, argv, "n:"))!=-1){ if(command == 'n'){ strNumProcess = optarg; break; } } int numProcess = atoi(strNumProcess); int pipes[numProcess][2]; int randomNum; // Variable to store the random number int randomNumSum=0; // Initialized variable to store the sum of random number /** A loop that creates specified number of processes**/ for(int i=0; i<numProcess; i++){ processCheck = fork(); // creates a child process. Usually fork() = 2^n processes if(processCheck < 0){ // Checks for the error in fork() printf("Error"); exit(1); // Terminates with error } else if(processCheck == 0){ close(pipes[i][0]); /** Child process**/ srand(time(NULL)+getpid()); // sets the randomness of the number associted with process id randomNum = rand()% 201 + (-100); // sets the range of random number from -100 to 100 and stores the random number in randomNum printf("%dn" , randomNum); // Prints out the random number write(pipes[i][1], &randomNum, sizeof randomNum); close(pipes[i][1]); exit(0);// Terminates successfully } else{ if(wait(NULL)){ // Waits for the child process to end and directs to parent process int v; if(read(pipes[i][0], &v, sizeof v)==sizeof(v)){ randomNumSum+=v; close(pipes[i][0]); } } } close(pipes[i][1]); } printf("%dn", randomNumSum); // Prints the sum of the random number return 0; }
程序在第二个过程后进入无限循环。
编辑
OP已经对这个问题做出了重大改变,这与昨天的问题不同。 这个答案今后可能再没有意义了。
结束编辑
这样做的原因是fork()
创建了一个具有自己的虚拟内存的新独立进程。 它只inheritance父级的值,分叉的进程不与父级共享变量。 因此randomNumSum
为每个孩子提供一个唯一变量,并且更改它不会影响父项的randomNumSum
。
你需要使用例如管道来进行父母和孩子之间的沟通,孩子们在管道中写下结果,父母从孩子那里读取。
#include #include #include #include #include #include int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "usage: %s num_of_childrenn", argv[0]); return 0; } int noc = atoi(argv[1]); if(noc <= 0) { fprintf(stderr, "Invalid number of childrenn"); return 1; } int pipes[noc][2]; pid_t pids[noc]; for(size_t i = 0; i < noc; ++i) { if(pipe(pipes[i]) == -1) { perror("pipe"); pids[i] = -2; // used later for error checking continue; } pids[i] = fork(); if(pids[i] == -1) { perror("fork"); continue; } if(pids[i] == 0) { // CHILD // closing reading end close(pipes[i][0]); srand(time(NULL)+getpid()); int r = rand()% 201 + (-100); printf("Child %zu: r = %dn", i, r); // sending value to parent write(pipes[i][1], &r, sizeof r); close(pipes[i][1]); return 0; } // closing writing end close(pipes[i][1]); } int sum = 0; for(size_t i = 0; i < noc; ++i) { if(pids[i] == -2) { fprintf(stderr, "Pipe could not be created for child %zun", i); continue; } if(pids[i] == -1) { fprintf(stderr, "Child %zu was not startedn", i); close(pipes[i][0]); continue; } int status; if(waitpid(pids[i], &status, 0) == -1) { fprintf(stderr, "Could not wait for child %zun", i); close(pipes[i][0]); continue; } if(WIFEXITED(status) && WEXITSTATUS(status) == 0) { int v; if(read(pipes[i][0], &v, sizeof v) != sizeof(v)) { fprintf(stderr, "Could not read from child %zun", i); close(pipes[i][0]); continue; } sum += v; close(pipes[i][0]); } else printf("Child %zu did not exit normallyn", i); } printf("The sum is: %dn", sum); return 0; }
给我输出:
Child 0: r = -6 Child 1: r = 63 Child 3: r = 78 Child 2: r = 77 Child 4: r = -47 The sum is: 165
所以这里的技术是用pipe
创建pipe
。 管道是单向数据通道,可用于进程间通信 引用 。 使用管道,两个进程可以相互通信,但管道只有一个方向。 在此示例中,子进程将写入管道,父进程将从管道中读取。
这就是为什么在做fork
之前,父进程创建管道,做fork
,然后关闭它的管道写入端。 孩子关闭它的管道读数端。 然后,子计算该值并将其计算的值写入管道,并以状态0存在。
创建子项后,父项等待子项终止。 如果子节点正常终止且退出状态为0,则父节点从管道读取并获取子节点的计算值。
顺便说一句,正如David C. Rankin在评论中指出的那样,你在[-100,100]范围内获得随机值的方法是不正确的。 rand()% 201 + (-100)
会给出介于-100和100之间的值,因为rand()%201
会给出0到200之间的值。
EDIT2
OP在评论中问道
根据我的理解,我可以只返回
randonNum
而不是exit(0)
并在我调用wait(NULL)
和call wait(randomNum)?
是的,您可以使用进程的退出状态将信息发送回父级,而无需创建管道。 但我认为由于以下原因,这不是一个特别好的解决方案:
因此,更改代码以在没有管道和使用退出状态的情况下执行相同的操作:
#include #include #include #include #include #include int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "usage: %s num_of_childrenn", argv[0]); return 0; } int noc = atoi(argv[1]); if(noc <= 0) { fprintf(stderr, "Invalid number of childrenn"); return 1; } pid_t pids[noc]; for(size_t i = 0; i < noc; ++i) { pids[i] = fork(); if(pids[i] == -1) { perror("fork"); continue; } if(pids[i] == 0) { // CHILD srand(time(NULL)+getpid()); int r = rand()% 201 + (-100); printf("Child %zu: r = %dn", i, r); exit(r); } } int sum = 0; for(size_t i = 0; i < noc; ++i) { if(pids[i] == -1) { fprintf(stderr, "Child %zu was not startedn", i); continue; } int status; if(waitpid(pids[i], &status, 0) == -1) { fprintf(stderr, "Could not wait for child %zun", i); continue; } if(WIFEXITED(status)) { int v = WEXITSTATUS(status); // checking if the child wrote a 8-bit negative value // in 2-complement format if(v > 127) v -= 256; printf("Parent: child %zu returned %dn", i, v); sum += v; } else fprintf(stderr, "Child %zu did exit abnormally, ignoringn", i); } printf("The sum is: %dn", sum); return 0; }
给我10个孩子的输出:
Child 0: r = -59 Child 1: r = 73 Child 2: r = 61 Child 3: r = 98 Child 4: r = 18 Child 6: r = 31 Child 5: r = -88 Parent: child 0 returned -59 Parent: child 1 returned 73 Parent: child 2 returned 61 Child 8: r = 58 Parent: child 3 returned 98 Parent: child 4 returned 18 Parent: child 5 returned -88 Child 7: r = 53 Parent: child 6 returned 31 Child 9: r = -43 Parent: child 7 returned 53 Parent: child 8 returned 58 Parent: child 9 returned -43 The sum is: 202
以上就是c/c++开发分享用于Linux的进程(Ubuntu)相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/549538.html