Linux
Ulrich Drepper's How To Write Shared Libraries is a good resource for learning more about the ELF format, about optimizing your shared objects, and how to control the visibility of program symbols in the generated binaries.
Interprocess Communication Mechanisms
Linux offers creating System V shared memory segments, which can be used for interprocess communication.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> // creating an IPC key key_t segmentKey = ftok(”path_to_some_existing_file", 'R') if (segmentKey == -1) { perror("could not create IPC key"); exit(1); } // accessing the shared memory segment, creating it if it doesn't exist int sharedMemoryID = shmget(segmentKey, SHM_SIZE, 0644 | IPC_CREAT) if (sharedMemoryID == -1) { perror("could not access (or create) the shared memory segment"); exit(1); } // attaching a pointer void* memoryPtr = shmat(sharedMemoryID, NULL, 0); if (*((char*)memoryPtr) == -1) { perror("could not attach a pointer to the shared memory segment"); exit(1); }
To learn more about shared memory segments, type
man ftok man shmget man shmat
Memory Mapped Files
Linux offers mapping files to memory regions, which enables working on the file contents much more efficiently, as if it is a memory region. For example, pointers can be used in a C/C++ program to edit the contents. The memory mapped region can be shared between processes. This allows the processes to operate on large files, for example in a writer-subscriber architecture, while preserving memory. Unlike the shared memory method described above, the contents of the shared memory region are written to a file and thus persist between sessions and even system reboots.
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> static const int MAX_INPUT_LENGTH = 50; int main(int argc, char** argv) { int fd = open(argv[1], O_RDWR | O_CREAT); char* shared_mem = mmap(NULL, MAX_INPUT_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (!strcmp(argv[2], "read")) { // continously listens to text messages from the 'write' process and writes to the terminal while (1) { shared_mem[MAX_INPUT_LENGTH-1] = '\0'; printf("%s", shared_mem); sleep(1); } } else if (!strcmp(argv[2], "write")) { // continuously sends the input from the terminal to the 'read' process while (1) { fgets(shared_mem, MAX_INPUT_LENGTH, stdin); } } else { printf("Unsupported command\n"); } }
To learn more about memory mapped files, refer to the man page
man mmap
Pipes
Pipes are another IPC mechanism where one process can send messages to another.
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <unistd.h> int main(void) { int pipeDescriptor[2]; pipe(pipeDescriptor); // writing to pipeDescriptor[0], reading from pipeDescriptor[1] if (!fork()) { printf(" CHILD: writing to pipe and exiting\n"); write(pipeDescriptor[1], "test", 5); } else { char buffer[5]; printf("PARENT: reading from pipe\n"); read(pipeDescriptor[0], buffer, 5); printf("PARENT: read \"%s\"\n", buf); wait(NULL); } return 0; }
To learn more about pipes, refer to the man page
man pipe
C++ Notes
Platform detection
To detect whether code is compiled for the Linux platform you can check if __linux__ is defined.
#ifdef __linux__
(here you can find preprocessor definitions for many operating systems)