要求用户多次输入的C程序
编写一个非常基本的C程序,演示共享内存。程序需要不断计算两个输入的总和,直到用户执行要求用户多次输入的C程序,c,shared-memory,C,Shared Memory,编写一个非常基本的C程序,演示共享内存。程序需要不断计算两个输入的总和,直到用户执行^C(此处未显示) 到目前为止,我的父母捕获用户输入,然后告诉孩子计算总和,然后父母打印总和(如分配所示) 附件是我的密码 // Fork the process while(1) {
^C
(此处未显示)
到目前为止,我的父母捕获用户输入,然后告诉孩子计算总和,然后父母打印总和(如分配所示)
附件是我的密码
// Fork the process
while(1) {
// Declare a shared memory integer array
int *shared_ints = mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
int x;
int y;
shared_ints[3] = 0;
if((pid = fork()) < 0) {
printf("Fork error \n");
exit(-1);
} else if(pid > 0 && shared_ints[3] == 0) { // Parent code
// Ask user for first input
printf("Enter your first number:");
scanf("%d", &x);
printf("\n");
// Ask user for second input
printf("Enter your second number:");
scanf("%d", &y);
printf("\n");
// Assign first value to shared memory
shared_ints[0] = x;
// Assign second value to shared memory
shared_ints[1] = y;
// Tell child that it can compute the sum now
shared_ints[3] = 1;
// Trap parent in a while-loop while the child
// computes the sum
while(shared_ints[3] == 1);
// Child has completed calculating the sum and
// the parent can print the sum
if(shared_ints[3] == 2) {
printf("The sum is: %d", shared_ints[2]);
printf("\n");
}
} else { // Child code
// Wait for parent to accept input values
while(shared_ints[3] == 0);
// Calculate the sum
shared_ints[2] = shared_ints[0] + shared_ints[1];
// Tell parent sum has been calculated
shared_ints[3] = 2;
}
}
我看到的一个有趣的错误是,在我打印总和之后,程序会按照此处的建议两次请求第一个输入:
输入第一个数字:输入第一个数字:3
,然后在第四次总和迭代中,它会在计算总和之前多次请求第二个数字 问题在于,您在每次迭代外部时都要进行分叉,因此第一次,您有一个孩子,然后您有一个孩子认为自己长大了,并且是家长(以及知道自己是家长的家长)。如果你继续下去,情况会变得更糟
另一个问题是在外部while
循环的每次迭代中分配共享内存。我不确定这到底是内存泄漏,但这可能不是个好主意
要修复:
- 将
mmap()
和fork()
移动到while(1)
循环之外
- 父进程将有一个循环-在它自己的函数中,而不是在
main()
,请-从用户读取,传输到子进程,从子进程读取结果,然后继续
- 子进程将有一个循环——请也在它自己的函数中——从父进程读取、计算并继续
- 确保孩子知道如何在父母退出时退出
- 理想情况下,使用非繁忙等待的同步机制。两个互斥量或两个信号量就好了。流程将等待被告知有工作要做,而不是在等待下一个任务时旋转轮子(非常快)
或多或少的工作代码
这使用了我编写的代码中的头“stderr.h”
和函数err\u setarg0()
和err\u syserr()
,因为错误报告非常重要,这使它变得简单。您应该能够从我这里找到使用该头和那些函数的工作版本的SO上的代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "stderr.h"
static void be_childish(int *shared_ints);
static void be_parental(int *shared_ints);
int main(int argc, char **argv)
{
const char *file = "fidget";
int shared_seg_size = 4 * sizeof(int);
err_setarg0(argv[0]);
if (argc > 1)
file = argv[1];
int fd = open(file, O_RDWR|O_CREAT, 0600);
if (fd < 0)
err_syserr("Failed to open file %s for read/write\n", file);
/* Assume sizeof(int) == 4 */
if (write(fd, "abcdefghijklmnop", shared_seg_size) != shared_seg_size)
err_syserr("Failed to write %d bytes to %s\n", shared_seg_size, file);
int *shared_ints = mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shared_ints == 0)
err_syserr("Failed to mmap file %s\n", file);
shared_ints[3] = 0;
int pid;
if ((pid = fork()) == -1)
err_syserr("Failed to fork\n");
else if (pid == 0)
be_childish(shared_ints);
else
be_parental(shared_ints);
return 0;
}
static void be_childish(int *shared_ints)
{
while (1)
{
// Wait for parent to generate input values
while (shared_ints[3] == 0 || shared_ints[3] == 2)
{
printf("Child: %d\n", shared_ints[3]);
usleep(500000);
}
if (shared_ints[3] != 1)
{
printf("Child: exiting\n");
return;
}
// Calculate the sum
shared_ints[2] = shared_ints[0] + shared_ints[1];
printf("Child: calculated %d + %d = %d\n", shared_ints[0], shared_ints[1], shared_ints[2]);
// Tell parent sum has been calculated
shared_ints[3] = 2;
}
}
static void be_parental(int *shared_ints)
{
while (1)
{
int x;
int y;
// Ask user for first input
printf("Enter your first number:");
if (scanf("%d", &x) != 1)
{
printf("Parent: exiting\n");
shared_ints[3] = -1; /* Tell child to exit */
return;
}
printf("\n");
// Ask user for second input
printf("Enter your second number:");
if (scanf("%d", &y) != 1)
{
printf("Parent: exiting\n");
shared_ints[3] = -1; /* Tell child to exit */
return;
}
printf("\n");
// Assign first value to shared memory
shared_ints[0] = x;
// Assign second value to shared memory
shared_ints[1] = y;
// Tell child that it can compute the sum now
shared_ints[3] = 1;
// Trap parent in a while-loop while the child
// computes the sum
while (shared_ints[3] == 1)
{
printf("Parent: %d\n", shared_ints[3]);
usleep(500000);
}
// Child has completed calculating the sum and
// the parent can print the sum
if (shared_ints[3] == 2)
{
printf("The sum is: %d", shared_ints[2]);
printf("\n");
}
else
{
printf("Parent: unexpected control %d - exiting\n", shared_ints[2]);
shared_ints[3] = -1; /* Tell child to exit */
return;
}
}
}
父母在孩子离开之前就离开了;这没什么大不了的。如果愿意,您可以将代码升级为使用wait()
来等待孩子退出。问题是,您在执行外部循环时,每次都要对外部进行迭代,因此第一次,您有一个孩子,然后您有一个认为自己已经长大并且是家长的孩子(以及知道自己是父母的父母)。随着你继续下去,情况会变得更糟
另一个问题是在外部while
循环的每次迭代中分配共享内存。我不确定这是否确实是内存泄漏,但这可能不是一个好主意
要修复:
- 将
mmap()
和fork()
移动到while(1)
循环之外
- 父进程将有一个循环-在它自己的函数中,而不是在
main()
,请-从用户读取,传输到子进程,从子进程读取结果,然后继续
- 子进程将有一个循环——请也在它自己的函数中——从父进程读取、计算并继续
- 确保孩子知道如何在父母退出时退出
- 理想情况下,使用一种同步机制,而不是忙着等待。两个互斥体或两个信号量就可以了。进程将等待被告知有工作要做,而不是在等待下一个任务时旋转轮子(非常快)
或多或少的工作代码
这使用了我编写的代码中的头“stderr.h”
和函数err\u setarg0()
和err\u syserr()
,因为错误报告非常重要,这使它变得很容易。您应该能够从我这里找到包含该头和这些函数的工作版本的代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "stderr.h"
static void be_childish(int *shared_ints);
static void be_parental(int *shared_ints);
int main(int argc, char **argv)
{
const char *file = "fidget";
int shared_seg_size = 4 * sizeof(int);
err_setarg0(argv[0]);
if (argc > 1)
file = argv[1];
int fd = open(file, O_RDWR|O_CREAT, 0600);
if (fd < 0)
err_syserr("Failed to open file %s for read/write\n", file);
/* Assume sizeof(int) == 4 */
if (write(fd, "abcdefghijklmnop", shared_seg_size) != shared_seg_size)
err_syserr("Failed to write %d bytes to %s\n", shared_seg_size, file);
int *shared_ints = mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shared_ints == 0)
err_syserr("Failed to mmap file %s\n", file);
shared_ints[3] = 0;
int pid;
if ((pid = fork()) == -1)
err_syserr("Failed to fork\n");
else if (pid == 0)
be_childish(shared_ints);
else
be_parental(shared_ints);
return 0;
}
static void be_childish(int *shared_ints)
{
while (1)
{
// Wait for parent to generate input values
while (shared_ints[3] == 0 || shared_ints[3] == 2)
{
printf("Child: %d\n", shared_ints[3]);
usleep(500000);
}
if (shared_ints[3] != 1)
{
printf("Child: exiting\n");
return;
}
// Calculate the sum
shared_ints[2] = shared_ints[0] + shared_ints[1];
printf("Child: calculated %d + %d = %d\n", shared_ints[0], shared_ints[1], shared_ints[2]);
// Tell parent sum has been calculated
shared_ints[3] = 2;
}
}
static void be_parental(int *shared_ints)
{
while (1)
{
int x;
int y;
// Ask user for first input
printf("Enter your first number:");
if (scanf("%d", &x) != 1)
{
printf("Parent: exiting\n");
shared_ints[3] = -1; /* Tell child to exit */
return;
}
printf("\n");
// Ask user for second input
printf("Enter your second number:");
if (scanf("%d", &y) != 1)
{
printf("Parent: exiting\n");
shared_ints[3] = -1; /* Tell child to exit */
return;
}
printf("\n");
// Assign first value to shared memory
shared_ints[0] = x;
// Assign second value to shared memory
shared_ints[1] = y;
// Tell child that it can compute the sum now
shared_ints[3] = 1;
// Trap parent in a while-loop while the child
// computes the sum
while (shared_ints[3] == 1)
{
printf("Parent: %d\n", shared_ints[3]);
usleep(500000);
}
// Child has completed calculating the sum and
// the parent can print the sum
if (shared_ints[3] == 2)
{
printf("The sum is: %d", shared_ints[2]);
printf("\n");
}
else
{
printf("Parent: unexpected control %d - exiting\n", shared_ints[2]);
shared_ints[3] = -1; /* Tell child to exit */
return;
}
}
}
父项在子项之前退出;这并不奇怪。您可以将代码升级为使用wait()
等待孩子退出(如果您愿意)。注意:在家长退出而孩子仍在等待家长输入值的情况下会出现问题-如果用户在共享输入[3]!=0时中断程序,则可能会发生这种情况
为了展示@Jonathan Leffler的优秀答案,我建议如下:
/* These are better declared outside the while loop */
// Declare a shared memory integer array
int *shared_ints = mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
int x;
int y;
// Fork the process
while(1) {
shared_ints[3] = 0;
if((pid = fork()) < 0) {
printf("Fork error \n");
exit(-1);
} else if(pid > 0 && shared_ints[3] == 0) { // Parent code
// Ask user for first input
printf("Enter your first number:");
scanf("%d", &x);
printf("\n");
// Ask user for second input
printf("Enter your second number:");
scanf("%d", &y);
printf("\n");
// Assign first value to shared memory
shared_ints[0] = x;
// Assign second value to shared memory
shared_ints[1] = y;
// Tell child that it can compute the sum now
shared_ints[3] = 1;
// Trap parent in a while-loop while the child
// computes the sum
while(shared_ints[3] == 1);
// Child has completed calculating the sum and
// the parent can print the sum
if(shared_ints[3] == 2) {
printf("The sum is: %d", shared_ints[2]);
printf("\n");
}
} else { // Child code
// Wait for parent to accept input values
while(shared_ints[3] == 0);
// Calculate the sum
shared_ints[2] = shared_ints[0] + shared_ints[1];
// Tell parent sum has been calculated
shared_ints[3] = 2;
/* Child process should finish, so it doesn't fork
and in the upper while loop. this is a fast way to do it */
exit(0);
}
}
/*最好在while循环之外声明*/
//声明共享内存整数数组
int*shared_ints=mmap(NULL,shared_seg_size,PROT_READ | PROT_WRITE,MAP_shared,fd,0);
int x;
int-y;
//分岔
而第(1)款{
共享整数[3]=0;
如果((pid=fork())<0){
printf(“Fork错误\n”);
出口(-1);
}如果(pid>0&&shared_int[3]==0){//父代码
//向用户请求第一次输入
printf(“输入您的第一个号码:”);
scanf(“%d”和&x);
printf(“\n”);
//请求用户进行第二次输入
printf(“输入您的秒
/* These are better declared outside the while loop */
// Declare a shared memory integer array
int *shared_ints = mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
int x;
int y;
// Fork the process
while(1) {
shared_ints[3] = 0;
if((pid = fork()) < 0) {
printf("Fork error \n");
exit(-1);
} else if(pid > 0 && shared_ints[3] == 0) { // Parent code
// Ask user for first input
printf("Enter your first number:");
scanf("%d", &x);
printf("\n");
// Ask user for second input
printf("Enter your second number:");
scanf("%d", &y);
printf("\n");
// Assign first value to shared memory
shared_ints[0] = x;
// Assign second value to shared memory
shared_ints[1] = y;
// Tell child that it can compute the sum now
shared_ints[3] = 1;
// Trap parent in a while-loop while the child
// computes the sum
while(shared_ints[3] == 1);
// Child has completed calculating the sum and
// the parent can print the sum
if(shared_ints[3] == 2) {
printf("The sum is: %d", shared_ints[2]);
printf("\n");
}
} else { // Child code
// Wait for parent to accept input values
while(shared_ints[3] == 0);
// Calculate the sum
shared_ints[2] = shared_ints[0] + shared_ints[1];
// Tell parent sum has been calculated
shared_ints[3] = 2;
/* Child process should finish, so it doesn't fork
and in the upper while loop. this is a fast way to do it */
exit(0);
}
}
if((pid = fork()) < 0) {