add forking example
This commit is contained in:
commit
c3c04b7697
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
zig-out
|
||||
zig-cache
|
4
README.md
Normal file
4
README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Shared Memory Examples In C
|
||||
|
||||
All of the C examples are setup to use the zig build system.
|
||||
You can download zig [here](https://ziglang.org/download/) (Use version 0.11.0) and just run `zig build run` in any example.
|
38
forking/build.zig
Normal file
38
forking/build.zig
Normal file
@ -0,0 +1,38 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
{
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "forking-simple",
|
||||
.root_source_file = .{ .path = "simple.c" },
|
||||
.optimize = optimize,
|
||||
.target = target
|
||||
});
|
||||
exe.linkLibC();
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
const run_step = b.step("run", "Run simple program");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
b.installArtifact(exe);
|
||||
}
|
||||
|
||||
{
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "forking-mutexes",
|
||||
.root_source_file = .{ .path = "mutexes.c" },
|
||||
.optimize = optimize,
|
||||
.target = target
|
||||
});
|
||||
exe.linkLibC();
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
const run_step = b.step("run-mutexes", "Run mutexes program");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
b.installArtifact(exe);
|
||||
}
|
||||
}
|
79
forking/mutexes.c
Normal file
79
forking/mutexes.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
// WARNING: This example does not work, I couldn't figure out why the child process goes into a deadlock on `pthread_mutex_lock`
|
||||
|
||||
struct shared_data {
|
||||
pthread_mutex_t mutex;
|
||||
int counter;
|
||||
};
|
||||
|
||||
void milli_sleep(int milliseconds) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||
nanosleep(&ts, &ts);
|
||||
}
|
||||
|
||||
float random_float() {
|
||||
return (float)rand()/(float)RAND_MAX;
|
||||
}
|
||||
|
||||
int random_range(int from, int to) {
|
||||
return random_float()*(to-from) + from;
|
||||
}
|
||||
|
||||
void run(const char *name, struct shared_data *data) {
|
||||
printf("[%s] started, mutex: %p\n", name, &data->mutex);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (pthread_mutex_lock(&data->mutex) != 0) {
|
||||
perror("pthread_mutex_lock");
|
||||
}
|
||||
|
||||
int counter = data->counter;
|
||||
milli_sleep(random_range(0, 100));
|
||||
data->counter = counter + 1;
|
||||
printf("[%s] counter is %d\n", name, counter + 1);
|
||||
|
||||
if (pthread_mutex_unlock(&data->mutex) != 0) {
|
||||
perror("pthread_mutex_unlock");
|
||||
}
|
||||
}
|
||||
printf("[%s] finished\n", name);
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct shared_data *shared_data = mmap(NULL, sizeof(struct shared_data), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
if (shared_data == NULL) {
|
||||
perror("mmap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&shared_data->mutex, NULL) < 0) {
|
||||
printf("Failed to initialise mutex\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
shared_data->counter = 0;
|
||||
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
srand(time(NULL)+1);
|
||||
run("Child ", shared_data);
|
||||
return 0;
|
||||
} else {
|
||||
srand(time(NULL)+2);
|
||||
run("Parent", shared_data);
|
||||
}
|
||||
|
||||
int child_status;
|
||||
waitpid(pid, &child_status, 0);
|
||||
}
|
||||
|
27
forking/simple.c
Normal file
27
forking/simple.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int main() {
|
||||
char parent_message[] = "hello";
|
||||
char child_message[] = "goodbye";
|
||||
|
||||
void* shmem = mmap(NULL, 128, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
memcpy(shmem, parent_message, sizeof(parent_message));
|
||||
|
||||
int pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
printf("Child read: %s\n", (char*)shmem);
|
||||
memcpy(shmem, child_message, sizeof(child_message));
|
||||
printf("Child wrote: %s\n", (char*)shmem);
|
||||
|
||||
} else {
|
||||
printf("Parent read: %s\n", (char*)shmem);
|
||||
sleep(1);
|
||||
printf("After 1s, parent read: %s\n", (char*)shmem);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user