gpt4 book ai didi

c - Linux的C语言中的进程(Ubuntu)

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:03:54 24 4
gpt4 key购买 nike

我想做的是:
编写一个c程序,它接受一个整数命令行参数n,
生成n进程,每个进程将在
-100和100,然后计算并打印出这些随机数的和。每个进程都需要打印出随机数
生成。
这就是我目前所拥有的:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>


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("%d\n" , 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("%d\n", randomNumSum); // Prints the sum of the random number

return 0;
}

程序在经过第二个进程后进入无限循环。

最佳答案

编辑
OP对这个问题做了重大的改变,这和昨天的问题不一样。这个答案从今以后可能就没有意义了。
结束编辑
原因是fork()创建了一个新的独立进程
拥有虚拟内存。它只继承父进程的值,分叉进程不共享变量
和父母在一起。所以randomNumSum对于每个孩子都是一个唯一的变量
更改它不会影响父对象的randomNumSum
您需要使用例如管道在父级和
子级,子级在管道中写入结果,父级从
孩子们。

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv)
{
if(argc != 2)
{
fprintf(stderr, "usage: %s num_of_children\n", argv[0]);
return 0;
}

int noc = atoi(argv[1]);

if(noc <= 0)
{
fprintf(stderr, "Invalid number of children\n");
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 = %d\n", 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 %zu\n", i);
continue;
}

if(pids[i] == -1)
{
fprintf(stderr, "Child %zu was not started\n", i);
close(pipes[i][0]);
continue;
}

int status;
if(waitpid(pids[i], &status, 0) == -1)
{
fprintf(stderr, "Could not wait for child %zu\n", 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 %zu\n", i);
close(pipes[i][0]);
continue;
}

sum += v;
close(pipes[i][0]);
} else
printf("Child %zu did not exit normally\n", i);
}

printf("The sum is: %d\n", 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创建管道。烟斗
是一个单向数据通道,可用于进程间通信 cite
有了管道,两个进程可以相互通信,但管道只有
一个方向。在本例中,子进程将写入管道并
父项将从管道中读取。
这就是为什么在执行 fork之前,父对象创建管道,并执行 fork
然后关闭“IT正在写入”管道的末端。孩子关上了它在看书
管道末端。然后子对象计算值并写入管道
它计算并存在于状态0中的值。
创建子级后,父级将等待子级终止。如果
儿童正常终止,退出状态0,家长从
并获取子项的计算值。
顺便说一句,正如 David C. Rankin在评论中指出的,您获取
范围为[-100,100]的随机值不正确。 rand()% 201 + (-100)
会给出-100到100之间的值,因为 rand()%201会给您一个
值介于0和200之间。
编辑2
Op在评论中问道
根据我的理解,我可以返回 randonNum而不是 exit(0)并在调用 wait(NULL)call wait(randomNum)?时进行计算吗?
是的,您可以使用进程的退出状态来将信息发送回
不需要创建管道的父对象。但我觉得这不是特别的
很好的解决方案,原因如下:
UNIX/POSIX中的退出状态是一个无符号的8位值,这意味着退出。
代码在[0,255]范围内。如果你的随机值是-1,
父进程将看到255。对你来说这不是问题,
因为对于大于127的值,可以减去256以得到
负值。
只能返回(无符号)8位值。如果你的孩子必须
发送更“复杂”的内容,如16位值、a floatdouble
struct,不能使用退出状态,所以
限制了你能回到父母身边的东西。当你想回来的时候
一些比8位值更“复杂”的东西,那么一个管道就是完美的工具。
我认为使用Exchange状态发送其他信息是一种黑客行为。
这不是一个错误值。退出状态的目的是一个过程
可以通过返回0告诉它的父进程没有错误退出,或者
退出一个错误,退出状态有错误代码。所以我
把它当作一个黑客,对我来说就像用螺丝刀代替锤子
钉钉子。
但是,您的 wait调用将无效,因为 wait需要一个指向
int并且您需要使用宏 WIFEXITEDWEXITSTATUS来获取
退出状态。但在这种情况下使用 wait的问题是 wait
错误时返回-1,您将无法判断返回的子级
-你要等多久
打电话来等其他孩子。孩子们的结局和你不一样
用叉子叉起来,这样你就需要跟踪哪个孩子被教育了。
使用 wait()要简单得多。使用 waitpid可以等待
特别的孩子。我个人更喜欢这里。
因此,在没有管道和使用退出状态的情况下,更改代码以执行相同的操作:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv)
{
if(argc != 2)
{
fprintf(stderr, "usage: %s num_of_children\n", argv[0]);
return 0;
}

int noc = atoi(argv[1]);

if(noc <= 0)
{
fprintf(stderr, "Invalid number of children\n");
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 = %d\n", 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 started\n", i);
continue;
}

int status;
if(waitpid(pids[i], &status, 0) == -1)
{
fprintf(stderr, "Could not wait for child %zu\n", 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 %d\n", i, v);
sum += v;
} else
fprintf(stderr, "Child %zu did exit abnormally, ignoring\n", i);
}

printf("The sum is: %d\n", 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 - Linux的C语言中的进程(Ubuntu),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49085988/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com