我正在为作业问题而苦苦挣扎。我被要求:
编写一个程序,其主例程从用户那里获取一个参数 n (n<40), i.e. passed to your program when it was invoked from the shell. Your program shall then create a shared memory and a child process. The shared memory shall have a size of BUF_SZ*sizeof(unsigned short), where BUF_SZ is defined as 5 using a macro, e.g. “#define BUF_SZ 5”.
子进程应该从父进程获取 n 的值(你实际上有多种选择)并创建一个长度为 n 且其元素类型为 unsigned short 的斐波那契数列。您可以在 (https://en.wikipedia.org/wiki/Fibonacci_number) 找到有关斐波那契数列的更多信息。
子进程应一次创建一个元素,并等待一个随机时间间隔( 0 <= time < 2 seconds) between generating elements of the sequence. As soon as an element is generated, the child places the element in the shared memory by organizing it as described in class.
父进程应立即在共享黄油上打印它收到的元素,而无需等待子进程退出。
#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 指针早一个时,子进程将元素输出到缓冲区。问题是父进程陷入了无限循环,它不会切换到子进程。我不确定如何进行。
几个问题...
while
循环。shm_open
使用NAME2
而不是NAME3
。这导致 inptr
和 outptr
指向 same 存储单元。因此,它们相互“别名”,并且它们将始终具有相同的值。inptr
和 outptr
应该有 volatile
[如 dimich 所述].int main(int argc,char **argv)
wait(NULL)
来收割孩子)。这是更正后的代码。是有注释的。我添加了一些调试打印来帮助:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/mman.h>
#define BUF_SZ 5
#define NAME "buffer"
#define NAME2 "inptr"
#define NAME3 "outptr"
#if DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
int
main(int argc,char **argv)
{
int fd[2];
int n = atoi(argv[1]);
unsigned short *data;
// NOTE/BUG: without volatile the optimizer could incorrectly elide code
#if 0
int *inptr;
int *outptr;
#else
volatile int *inptr;
volatile int *outptr;
#endif
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 = 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 = mmap(NULL, size2, PROT_READ | PROT_WRITE, MAP_SHARED, shmid2, 0);
// NOTE/BUG: this uses the same file as shmid2, so inptr are aliased together
#if 0
int shmid3 = shm_open(NAME2, O_CREAT | O_RDWR, 0666);
#else
int shmid3 = shm_open(NAME3, O_CREAT | O_RDWR, 0666);
#endif
ftruncate(shmid3, size2);
outptr = mmap(NULL, size2, PROT_READ | PROT_WRITE, MAP_SHARED, shmid3, 0);
#if 0
memset((void *) inptr, 0, size2); // in variable
memset((void *) outptr, 0, size2); // out variable
#else
*inptr = 0;
*outptr = 0;
#endif
pipe(fd);
pid_t pid = fork();
if (pid > 0) {
write(fd[1], &n, sizeof(n)); // write n value to child
// NOTE/FIX: we need an outer loop to get all numbers from the child
while (1) {
while (*inptr == *outptr);
printf("parent: %i\n", data[*outptr]);
fflush(stdout);
*outptr = (*outptr + 1) % BUF_SZ;
dbgprt("parent: inptr=%d outptr=%d\n",*inptr,*outptr);
}
}
else if (pid == 0) {
read(fd[0], &n, sizeof(n)); // get n value from parent
int prev = 0;
int curr = 1;
int tmp;
dbgprt("child: n=%d\n",n);
for (int i = 0; i <= n; i++) {
while (((*inptr + 1) % BUF_SZ) == *outptr);
if (i == 0) {
data[*inptr] = 0;
dbgprt("child: i0\n");
*inptr = (*inptr + 1) % BUF_SZ;
}
else if (i == 1) {
dbgprt("child: i1\n");
data[*inptr] = 1;
*inptr = (*inptr + 1) % BUF_SZ;
}
tmp = curr;
curr += prev;
prev = tmp;
printf("curr=%d\n",curr);
data[*inptr] = curr;
*inptr = (*inptr + 1) % BUF_SZ;
dbgprt("child: inptr=%d outptr=%d\n",*inptr,*outptr);
}
}
else {
printf("failed");
}
return 0;
}
在上面的代码中,我使用了
cpp
条件来表示旧代码与新代码:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
注意:这可以通过运行文件来清理
unifdef -k