我在努力解决家庭作业的问题。我被要求:
编写一个程序,其主例程从用户处获得一个参数n(n〈40),即从 shell 调用时传递给您的程序。然后您的程序应创建一个共享内存和一个子进程。共享内存的大小应为BUF_SZ*sizeof(无符号短整型),其中BUF_SZ使用宏定义为5,例如“#define BUF_SZ 5”。
子进程应该从父进程获得n的值(实际上有多种选择),并创建一个长度为n且元素类型为unsigned short的斐波那契数列,您可以在(https://en.wikipedia.org/wiki/Fibonacci_number)中找到关于斐波那契数列的更多信息。
子进程将创建元素,一次一个,并在生成序列元素之间等待一个随机的时间间隔(0〈= time〈2秒)。一旦元素生成,子进程将按照类中描述的方式组织元素,将其放入共享内存中。
父进程应立即打印其在共享缓冲器上接收到的元素,而无需等待子进程退出。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#define BUF_SZ 5
#define NAME "buffer"
#define NAME2 "inptr"
#define NAME3 "outptr"
int main() {
int fd[2];
int n = atoi(argv[1]);
unsigned short *data;
int* inptr;
int* outptr;
int size = BUF_SZ * sizeof(unsigned short);
int size2 = sizeof(int);
/*while(n >= 40 || n <= 0) {
printf("Enter a positive integer less than 40: ");
scanf("%i", &n);
}*/
int shmid = shm_open(NAME, O_CREAT|O_RDWR, 0666);
ftruncate(shmid, size);
data = (unsigned short*) mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
int shmid2 = shm_open(NAME2, O_CREAT|O_RDWR, 0666);
ftruncate(shmid2, size2);
inptr = (int*) mmap(NULL, size2, PROT_READ|PROT_WRITE, MAP_SHARED, shmid2, 0);
int shmid3 = shm_open(NAME2, O_CREAT|O_RDWR, 0666);
ftruncate(shmid3, size2);
outptr = (int*) mmap(NULL, size2, PROT_READ|PROT_WRITE, MAP_SHARED, shmid3, 0);
memset(inptr, 0, size2); //in variable
memset(outptr, 0, size2); //out variable
pipe(fd);
pid_t pid = fork();
if(pid > 0) {
write(fd[1], &n, sizeof(n)); //write n value to child
while (*inptr == *outptr);
printf("%i\n", data[*outptr]);
fflush(stdout);
*outptr = (*outptr + 1) % BUF_SZ;
}
else if(pid == 0) {
read(fd[0], &n, sizeof(n)); //get n value from parent
int prev = 0;
int curr = 1;
int tmp;
for(int i = 0; i <= n; i++) {
while (((*inptr + 1) % BUF_SZ) == *outptr);
if(i == 0) {
data[*inptr] = 0;
*inptr = (*inptr + 1) % BUF_SZ;
}
else if(i == 1) {
data[*inptr] = 1;
*inptr = (*inptr + 1) % BUF_SZ;
}
tmp = curr;
curr += prev;
prev = tmp;
data[*inptr] = curr;
*inptr = (*inptr + 1) % BUF_SZ;
}
}
else {
printf("failed");
}
return 0;
}
我为fib序列的元素以及in和out指针创建了共享内存缓冲区。In向缓冲区写入,out从缓冲区读取。父进程检查in和out指针是否相等。当它们不相等时,它从缓冲区中读取。2当入指针比出指针提前一个指针时,子进程输出元素到缓冲区。问题是父进程陷入了无限while循环,无法切换到子进程,我不知道该如何继续。
1条答案
按热度按时间xfb7svmp1#
一些问题...
1.在父循环中只获取一个数字,需要一个外部的
while
循环。1.最后一个
shm_open
使用NAME2
而不是NAME3
,这会导致inptr
和outptr
指向同一个内存单元,因此,它们彼此"别名",并且它们将始终是相同的值。inptr
和outptr
上面应该有volatile
[正如dimich提到的]。1.您需要
int main(int argc,char **argv)
1.父节点将在从子节点接收到最终数字后 * 无限 * 循环。
1.虽然我没有在下面的代码中这样做,但子循环可以再发送一个final值,即sentinel(告诉父循环到此为止),当父循环看到这个sentinel时,它就跳出外循环(然后执行
wait(NULL)
以获取子循环)。1.由于斐波那契数列不能为0,因此它是一个不错的标记值。
下面是正确的代码。它是带注解的。我添加了一些调试打印来提供帮助:
在上面的代码中,我使用了
cpp
条件来表示旧代码和新代码:注意:通过
unifdef -k
运行文件可以清除此问题