Definition:

Process:

get_pid()
  • Get process id of the current process
pid_t fork(void)
  • Create a new child process and return process id
  • The child process will continue to execute the same code as the parent
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main() {
    int num_children = 3; 
    pid_t pid;
 
    for (int i = 0; i < num_children; i++) {
        pid = fork();  
        if (pid < 0) {
            perror("fork");
            exit(1);
        } else if (pid == 0) { // the child sees this
            printf("Child process %d, PID: %d\n", i + 1, getpid());
            exit(0);  
        } else { // parent sees this
            printf("Parent created child %d, PID: %d\n", i + 1, pid);
        }
    }
 
    printf("Parent process complete\n");
    return 0;
}
void exit(int __status)
  • Terminate execution with status
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main() {
    pid_t pid;
    int status;
 
    pid = fork();
 
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid == 0) {
        printf("Child process PID: %d\n", getpid());
        sleep(3);  
        printf("Child process is exiting...\n");
        exit(5); 
    } else {
        printf("Parent process PID: %d waiting for child to terminate...\n", getpid());
		// pass by ref
        wait(&status);
        if (WIFEXITED(status)) {
            printf("Child terminated normally with exit status: %d\n", WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
            printf("Child was terminated by a signal: %d\n", WTERMSIG(status));
        }
 
        printf("Parent process finished.\n");
    }
 
    return 0;
}
void abort()
kill()

Shared memory

key_t ftok(const char *path, int id)
  • Generate an interprocess communication (IPC) key
  • returns a key based on path and id that is usable in subsequent calls to msgget(), semget(), and shmget()
int shmget(key_t __key, size_t __size, int __shmflg)
  • SHared Memory GET
  • Creates or retrieves a shared memory segment with the given key, size, and permissions.
void *shmat(int __shmid, const void *__shmaddr, int __shmflg)
  • SHared Memory ATtach
  • Attach shared memory segment to current process’s address space
int shmdt(const void *__shmaddr)
  • SHared Memory DeTach
  • Detach shared memory segment from current process’s address space
int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf)
  • SHared Memory ConTroL
  • Control the shared memory, eg: remove it
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
 
#define SHM_SIZE 1024 
int main() {
    pid_t pid;
    key_t key = ftok("shmfile", 65);  // Generates a unique key for the shared memory segment
    int shmid;
    char *shared_memory;
 
    shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        exit(1);
    }
 
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }
 
    if (pid == 0) {
        printf("Child process writing to shared memory...\n");
		// Attaches the shared memory segment to the child process's address space.
        shared_memory = (char *)shmat(shmid, NULL, 0);
        if (shared_memory == (char *)-1) {
            perror("shmat failed");
            exit(1);
        }
		// copy n or less string to memory
        strncpy(shared_memory, "Hello from child process!", SHM_SIZE);
 
        shmdt(shared_memory);
 
        printf("Child process finished writing.\n");
    } else {
        wait(NULL); 
 
        printf("Parent process reading from shared memory...\n");
 
        shared_memory = (char *)shmat(shmid, NULL, 0);
        if (shared_memory == (char *)-1) {
            perror("shmat failed");
            exit(1);
        }
 
        printf("Data read from shared memory: %s\n", shared_memory);
 
        shmdt(shared_memory);
		// remove the segment
        shmctl(shmid, IPC_RMID, NULL);
 
        printf("Parent process finished reading and cleaned up shared memory.\n");
    }
 
    return 0;
}
 

Thread

int pthread_create(pthread_t *__restrict__ __newthread, const pthread_attr_t *__restrict__ __attr, void *(*__start_routine)(void *), void *__restrict__ __arg)
  • Create a new thread, starting with execution of START-ROUTINE getting passed ARG
    • pass a function into it
  • Creation attributed come from ATTR.
  • The new handle is stored in *NEWTHREAD.
int pthread_join(pthread_t __th, void **__thread_return)
  • Make calling thread wait for termination of the thread th
  • The exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN is not NULL
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
#define NUM_THREADS 5  
 
typedef struct {
    int thread_id;
    int sum;
} thread_data_t;
 
void* compute_sum(void* arg) {
    thread_data_t* data = (thread_data_t*) arg;
    data->sum = 0;
 
    for (int i = 1; i <= 10; i++) {
        data->sum += i + data->thread_id * 10;
    }
 
    printf("Thread %d calculated sum: %d\n", data->thread_id, data->sum);
    pthread_exit(NULL);
}
 
int main() {
    pthread_t threads[NUM_THREADS];
    thread_data_t thread_data[NUM_THREADS];
 
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].thread_id = i;
        int result = pthread_create(&threads[i], NULL, compute_sum, &thread_data[i]);
        
        if (result != 0) {
            printf("Error creating thread %d\n", i);
            return 1;
        }
    }
 
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
 
    printf("All threads have finished execution.\n");
 
    return 0;
}
int pthread_mutex_init(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr)
  • Initialize a mutex.
  • A Mutex Lock (pthread_mutex_t mutex)
int pthread_mutex_destroy(pthread_mutex_t *__mutex)
  • Destroy a mutex
int pthread_mutex_lock(pthread_mutex_t *__mutex)
  • Lock a mutex for the current thread
int pthread_mutex_unlock(pthread_mutex_t *__mutex)
  • Unlock a locked mutex
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
#define NUM_THREADS 5
#define INCREMENTS_PER_THREAD 100000
 
long long shared_counter = 0;
 
pthread_mutex_t mutex;
 
void* increment_counter(void* arg) {
    for (int i = 0; i < INCREMENTS_PER_THREAD; i++) {
        pthread_mutex_lock(&mutex);
        shared_counter++;
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
 
int main() {
    pthread_t threads[NUM_THREADS];
    pthread_mutex_init(&mutex, NULL);
    
    for (int i = 0; i < NUM_THREADS; i++) {
        if (pthread_create(&threads[i], NULL, increment_counter, NULL) != 0) {
            perror("Failed to create thread");
            return 1;
        }
    }
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    printf("Final counter value: %lld\n", shared_counter);
    pthread_mutex_destroy(&mutex);
 
    return 0;
}