/*---------------------------------------------------------------------+ | cleanup () | | ==================================================================== | | | | Function: Closes all of the pipes, kills all of the child | | processes and exits the program... | | | +---------------------------------------------------------------------*/ void cleanup() { int i; if (getpid() == parent_pid) { delete_semaphores(); for (i = 0; i < num_children; i++) { if (pid[i] > (pid_t) 0 && kill(pid[i], SIGKILL) < 0) sys_error("signal failed", __LINE__); } } exit(-1); }
void sig_end_handler(int signal_number) { if (signal_number == SIGINT || signal_number == SIGTERM) { shmdt(shared_mem_ptr); shmctl(shmid, IPC_RMID, NULL); log_message("Shared memory deleted from system", LOG_DEBUG); delete_semaphores(); remove_lock(); log_message("Shutting down streams server", LOG_INFO); exit(EXIT_SUCCESS); } }
/*---------------------------------------------------------------------+ | main | | ==================================================================== | | | | Function: Main program (see prolog for more details) | | | | Returns: (0) Successful completion | | (-1) Error occurred | | | +---------------------------------------------------------------------*/ int main(int argc, char **argv) { int fd; /* Misc file descriptor */ int i; /* Misc loop index */ int shmem_size; /* Size (in bytes) of shared memory segment */ int status; /* Child processes exit status */ unsigned char *ptr; /* Misc pointer */ unsigned char data = 0; /* Value written into shared memory segment */ unsigned char *shmptr; /* Shared memory segment address */ unsigned long cksum; /* Shared memory segment checksum */ /* * Parse command line arguments and print out program header */ parse_args(argc, argv); printf("%s: IPC Shared Memory TestSuite program\n", *argv); /* * Setup the signal handlers (in case user aborts program). * * Create the semaphores to insure exclusive writes to the * shared memory segment. * * Save the parent process id and initialize the array of child * process ids. */ setup_signal_handlers(); create_semaphores(); parent_pid = getpid(); for (i = 0; i < num_children; i++) pid[i] = (pid_t) 0; /* * Create a shared memory segment for storing the read count * (number of child processes reading shared data) * After creating the shared memory segment, initialize it. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); if ((read_count = (int *) mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); *read_count = 0; /* * Create a shared memory segment for storing the child * processes checksums by memory mapping /dev/zero. * After creating the shared memory segment, initialize it. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); shmem_size = sizeof(unsigned long) * num_children; if ((checksum = (unsigned long *) mmap(0, shmem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); for (i = 0; i < num_children; i++) *(checksum + (sizeof(unsigned long) * i)) = 0; /* * Create the "scratch" shared memory segment for storing * a series of values by memory mapping /dev/zero. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); printf("\n\tGet shared memory segment (%d bytes)\n", buffer_size); if ((shmptr = mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); /* * Obtain an exclusive "write" lock on the shared memory data * segment -- get lock now to insure the parent process gets * first access to the segment. */ lock_resource(WRITE); /* * Spawn all N child processes. Each child process will compute * the checksum of the shared memory segment and will store * the results in the other shared memory segment accessible * by the parent. */ printf("\n\tSpawning %d child processes ... \n", num_children); for (i = 0; i < num_children; i++) { if ((pid[i] = fork()) == (pid_t) 0) { child(i, shmptr); exit(0); } else if (pid[i] < (pid_t) 0) sys_error("fork failed", __LINE__); } /* * Fill the "scratch" shared memory segment up with data and * compute the segments checksum. Release "write" lock after * completing so that the child processes may begin to read the * data. */ printf("\n\tParent: calculate shared memory segment checksum\n"); cksum = data = 0; for (ptr = shmptr; ptr < (shmptr + buffer_size); ptr++) { *ptr = (data++) % (UCHAR_MAX + 1); cksum += *ptr; } printf("\t shared memory checksum %08lx\n", cksum); unlock_resource(WRITE); /* * Wait for the child processes to compute the checksums and complete. * After the processes complete, check their exit status to insure * that they ran to completion and then verify the corresponding * checksum. */ for (i = 0; i < num_children; i++) { waitpid(pid[i], &status, 0); if (!WIFEXITED(status)) sys_error("child process terminated abnormally", __LINE__); if (cksum != *(checksum + (sizeof(unsigned long) * i))) { printf("checksum [%d] = %08lx\n", i, checksum[i]); error("checksums do not match", __LINE__); } } printf("\n\tParent: children calculated segment successfully\n"); /* * Program completed successfully, cleanup semaphores and exit. */ delete_semaphores(); printf("\nsuccessful!\n"); return (0); }