我有一个项目来说明如何在C中使用共享内存。这是我在本学期为我的项目建议的任务:以特殊方式将二维数组中的所有元素相加:
- 从用户输入行大小(m)和列大小(n),例如m = 4,n = 3.
- 将调用该程序,例如:myadder 9 8 7 3 2 1 2 3 4 2 10 12(这12个数字输入由空格或返回键分隔)
- 创建一个足够大小的共享内存1d数组来容纳整个上面的2d数组
- 然后,创建一个大小为m行的共享内存1d数组。此数组将用于存储计算后每行的总数
- 程序然后为数组中的每一行分叉一个子进程。这个子进程将总计其关联的行,只有它来自共享内存的行,并将结果存储在另一个1d数组中的关联元素中,称为total_row
- 父进程将等待所有子进程完成,然后将所有元素添加到total_row中。
你能给我提示完成上述任务吗?
答案 0 :(得分:1)
我相信这应该可以解决问题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
int main ()
{
int w, h, i, j;
/* Read the width and height */
scanf ("%d %d", &w, &h);
/* Create and read the entire array */
int *arr = malloc (w * h * sizeof (int));
for (i = 0; i < w * h; ++i)
scanf ("%d", &arr[i]);
/* Obtain a shared memory segment with the key 42 */
int shm = shmget (42, h * sizeof (int), IPC_CREAT | 0666);
if (shm < 0)
{
perror ("shmget");
return 1;
}
/* Attach the segment as an int array */
int *row = shmat (shm, NULL, 0);
if (row < (int *) NULL)
{
perror ("shmat");
return 1;
}
for (i = 0; i < h; ++i)
/* Create h children and make them work */
if (!fork ())
{
for (j = row[i] = 0; j < w; ++j)
row[i] += arr[i * w + j];
return 0;
}
/* Wait for the children to finish up */
for (i = 0; i < h; ++i)
wait (&j);
/* Sum the row totals */
for (i = j = 0; i < h; ++i)
j += row[i];
printf ("%d\n", j);
/* Detach the shared memory segment and delete its key for later reuse */
shmdt (row);
shmctl (shm, IPC_RMID, NULL);
free (arr);
return 0;
}
答案 1 :(得分:1)
考虑以下数组声明:
int arr [8];
当我们做出此声明时,内存会发生什么? 32个字节立即保留在内存中,每个4个字节用于8个整数。由于数组未被初始化,因此其中存在的所有8个值都是垃圾值。这是因为 假定此数组的存储类为AUTO。如果存储类声明为STATIC,则所有数组元素的默认初始值都为0.无论是初始值,所有数组元素都将始终存在于连续的内存位置。 存储器中阵列元素的这种排列如图
所示12 34 66 -45 23 346 77 90 65508 65512 65516 65520 65524 65528 65532 65536
答案 2 :(得分:0)
以下代码使用2个共享内存段..
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_2D 12345
#define KEY_ROW 54321
int main(int argc, char **argv) {
int rows, cols;
scanf("%d %d", &rows, &cols);
if(rows <= 0 || cols <= 0) {
printf("invalid input\n");
return 1;
}
int *dataa_user = NULL; /* To get user input for 2D array */
int i = 0;
int shm_2d = -1;
dataa_user = (int *) malloc(rows * cols * sizeof(int));
/* Do you need to take input from user as 2D array? and then
* convert it back to 1D array?
* I wonder as this is probably your assignment to understand
* some C and Unix concepts
*/
for(i = 0; i < rows * cols; i ++)
scanf("%d", &dataa_user[i]);
/* Creating shared memory that holds 2D array as 1D array */
shm_2d = shmget(KEY_2D, rows * cols * sizeof (int), IPC_CREAT | 0666);
if(shm_2d < 0) {
perror("shmget");
if(dataa_user) free(dataa_user);
dataa_user = NULL;
return 1;
}
/* Attach to the shared memory */
void *data_2d = shmat(shm_2d, NULL, 0);
if(data_2d == (void *)-1) {
perror("shmat");
shmctl (shm_2d, IPC_RMID, NULL);
if(dataa_user) free(dataa_user);
dataa_user = NULL;
return 1;
}
int shm_row = -1;
/* Copy the 1D array to shared memory */
memcpy( data_2d, dataa_user, rows * cols * sizeof(int));
free(dataa_user);
dataa_user = NULL;
/* Creating shared memory to keep the sum of each row as 1D array */
shm_row = shmget(KEY_ROW, rows * sizeof (int), IPC_CREAT | 0666);
if(shm_row < 0) {
perror("shmget");
shmdt(data_2d);
shmctl (shm_2d, IPC_RMID, NULL);
return 1;
} /* this closing brace was missed when i posted it first time.. */
/* Attach to the shared memory */
void *data_row = shmat(shm_row, NULL, 0);
if(data_row == (void *)-1) {
perror("shmat");
shmdt (data_2d);
shmctl (shm_2d, IPC_RMID, NULL);
shmctl (shm_row, IPC_RMID, NULL);
return 1;
}
/* Initialize it to 0. */
memset(data_row, 0, rows * sizeof(int));
for(i = 0; i < rows; i ++) {
if(!fork()) {
int k = 0;
int *dataa_2d = (int *)data_2d;
int *total_row = (int *)data_row;
for(; k < cols; k ++)
total_row[i] += dataa_2d[i * cols + k]; //add data to shm[row index] for each col in that row
return 0;
}
}
int sts = 0;
for(i = 0; i < rows; i ++) {
wait(&sts); /* wait for all the children to exit. */
}
int total_2d = 0;
int *total_row = (int *)data_row;
for(i = 0; i < rows; i ++) {
total_2d += total_row[i]; /* main process adding up all the row sum values */
}
printf("%d\n", total_2d);
/* clean up of IPC(shms used) */
shmdt(data_2d);
shmdt(data_row);
shmctl (shm_2d, IPC_RMID, NULL);
shmctl (shm_row, IPC_RMID, NULL);
return 0;
}
你的问题陈述只要求使用fork()系统调用..所以,这样的问题很简单(利用COW)..
(如果您应该使用exec()系统调用,那么它可能有助于您了解linux系统中的实际情况。此外,如果为每个子进程分配了total_row的总和,例如总计到第3个共享内存或者其他内容,它有助于理解同步..)
无论如何,希望这会有所帮助..