说明:我正在尝试使用共享内存和信号量的程序,以允许多个子进程操纵共享内存中的共享数据。我在xcode上编写了该程序,它在mac os终端中运行良好,但给了我shmget:在Linux中找不到共享内存。
运行ipcs时,我注意到它确实创建了共享内存并标记为删除,但是重新启动似乎无济于事。我必须手动删除一个。即使那样,它仍然不起作用。但是,Mac OS终端运行正常,程序甚至可以运行...我不知道该如何解决。请帮忙。非常感谢!!!
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <random>
#include <chrono>
#include <sys/sem.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
/*************************************************************************
***************** CONSTANT AND STRUCT DECLARATIONS **********************
*************************************************************************/
#define RESOURCES 4 /* Number of Resources */
#define PROCESS 10 /* Number of child process */
#define LOOP_NUMBER 5 /* Number of Loops per process */
struct Memory { /* Structure to store resources */
float var[RESOURCES];
};
/*************************************************************************
**************************** FUNCTIONS **********************************
*************************************************************************/
/* Function: sem_lock. Locks the semaphore for exclusive access to shared memory region.
* input: semaphore ID, process ID
* output: none
*/
int sem_lock(int resource_number, int semID, int process_id) {
/* structure for semaphore operation */
struct sembuf sem_op;
/* wait on semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
//cout << "Process " << process_id << " locks." << endl;
//semop (semID, &sem_op, 1);
return
semop (semID, &sem_op, 1);
}
/* function: sem_unlock. Unlocks the semaphore.
* input: semaphore ID, process ID
* output: none
*/
void sem_unlock(int resource_number, int semID, int process_id) {
/* structure for semaphore operation */
struct sembuf sem_op;
/* wait on semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
//cout << "Process " << process_id << " unlocks." << endl;
//semop (semID, &sem_op, 1);
semop (semID, &sem_op, 1);
}
/*************************************************************************
**************************** MAIN ****************************************
**************************************************************************/
int main (int argc, char *argv[]) {
pid_t childPid[PROCESS];
key_t ShmKey, semKey;
int ShmID,semID;
int rc; /* return value of system calls. */
struct Memory *mPtr;
union semun { /* semaphore value, for semctl() */
int val;
ushort* array;
} sem_val;
struct sembuf semPtr;
//Initialize random seed
//srand(time(NULL));
/* This gives random distribution for which resources to choose */
//uniform_real_distribution<int> resource_dist (0, 5); // this gives range [0, 5)
/* This gives random distribution for number of loops each process run for */
//uniform_real_distribution<int> loop_dist (5, 16); // this gives range [0, 5)
//Create semaphore
semKey = ftok("./", 's');
semID = semget(semKey, 1, IPC_CREAT | 0600);
if (semID == -1) {
perror ("semID fails");
exit(1);
}
/* Initialize the first (and single) semaphore to '1' */
sem_val.val = 1;
rc = semctl(semID, 0, SETVAL, sem_val);
if (rc == -1) {
switch (errno) {
case EACCES: cout <<"access";
case EINVAL: cout <<"index";
case ERANGE: cout <<"range";
};
cout << endl;
perror ("semctl fails");
exit(1);
}
//Create shared memory
ShmKey = ftok("./", 'u');
ShmID = shmget (ShmKey, sizeof(struct Memory), IPC_CREAT | 06666);
//If fails to get shared memory id
if (ShmID < 0) {
perror ("shmget");
exit(1);
}
mPtr = (struct Memory *) shmat (ShmID, NULL, 0);
//Initialize struct
for (int i = 0; i < RESOURCES; i++) {
mPtr->var[i] = i*10;
}
cout << "------------------------------" << endl; //space
for (int i = 0; i < RESOURCES; i++) {
printf("%d: %f, ",i, mPtr->var[i]);
}
cout << "\n------------------------------" << endl; //space
//Create 10 child process
for (int childIndex = 0; childIndex < PROCESS; childIndex++) {
childPid[childIndex] = fork();
if (childPid[childIndex] < 0) {
perror ("fork fails");
exit(1);
}
//Inside child process
if (childPid[childIndex] == 0) {
//Link to shared memory
mPtr = (struct Memory *) shmat (ShmID, NULL, 0);
//Loop
for (int loop = 0; loop < (childIndex+1)*LOOP_NUMBER; loop++) {
/* Use mt19937 generator to create random values of beta and chosen_resource */
mt19937 generator(chrono::high_resolution_clock::now().time_since_epoch().count());
uniform_real_distribution<float> beta_dist (-5, 5);
float random = beta_dist(generator); /* random value obtained from generator */
float beta = random / 10;
int chosen_resource = abs((int)random) % 4 ;
/* Adding beta operation */
cout << sem_lock(chosen_resource, semID, getpid());
cout << endl;
printf("%d locked semaphore\n", getpid());
printf("%d-----Adding %f to variable %d\n", getpid(), beta, chosen_resource);
mPtr->var[chosen_resource] += beta;
printf("%d is unlocking semaphore\n", getpid());
sem_unlock(chosen_resource, semID, getpid());
}
exit(0);
}
else if (childPid > 0) {
int status = 0;
pid_t pid;
int count = PROCESS;
while (count > 0) {
pid = wait(&status);
printf("Child with PID %ld exited.\n", (long)pid);
--count;
}
}
}
//Get status of children processes.
//int status = 0;
//pid_t pid;
//int count = PROCESS;
//while (count > 0) {
// pid = wait(&status);
// printf("Child with PID %ld exited.\n", (long)pid);
// --count;
//} */
//Get results
cout << "------------------------------" << endl; //space
//Print out results
for (int i = 0; i < RESOURCES; i++) {
printf("%d: %f, ",i, mPtr->var[i]);
}
cout << "\n------------------------------" << endl; //space
//Detach from shared memory
shmdt((void *) mPtr);
//Delete shared memory
shmctl(ShmID, IPC_RMID, NULL);
return 0;
//Remove semaphore
semID = semget(semKey, 1, 0);
if(semctl(semID, 0, IPC_RMID) < 0) {
perror ("Fail to remove semaphore");
exit(1);
}
exit (0);
}