Skip to content

Commit

Permalink
Merge pull request #7 from linomp/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
linomp authored Aug 23, 2024
2 parents b309014 + cc6bf23 commit 30d8433
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"files.associations": {
"*html": "html",
"unistd.h": "c"
}
}
18 changes: 18 additions & 0 deletions ostep/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CC=gcc
CCOPTS=#-Wall -Wextra
LIBS=

SRCS=$(wildcard *.c)
TARGETS=$(SRCS:.c=)

.PHONY: all clean pristine

all: $(TARGETS)

clean:
rm -f $(TARGETS) & rm -f *.output

pristine: clean all

%: %.c
$(CC) $(CCOPTS) -o $@ $< $(LIBS)
43 changes: 43 additions & 0 deletions ostep/ex5_1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
int* x = (int*)malloc(sizeof(int));

int rc = fork();

if (rc == 0) {
for (int i = 0; i <= 10; i++) {
printf("child | x=%d\n", (*x)++);
usleep(1);
}

} else {
for (int i = 0; i <= 10; i++) {
printf("parent| x=%d\n", (*x)++);
usleep(1);
}

wait(NULL);
}

return 0;
}

/*
Q: Write a program that calls fork(). Before calling fork(), have the
main process access a variable (e.g., x) and set its value to something (e.g.,
100). What value is the variable in the child process? What happens to the
variable when both the child and parent change the value of x?
A:
No race condition happens because they don't share memory actually.
Child process gets its own "private memory" (copy of parent's address space)
Therefore parent & child modify their own copy of x, indepedently.
Things would break if they were using shared memory.
note: Even if x is a pointer, nothing changes!
*/
47 changes: 47 additions & 0 deletions ostep/ex5_2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
int fd = open("./ex5_2.output", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
int rc = fork();

if (rc == 0) {
char* msg = "msg from child\n";

for (int i = 0; i < 5; i++) {
write(fd, msg, strlen(msg));
usleep(100);
}

} else {
char* msg = "msg from parent\n";
write(fd, msg, strlen(msg));

for (int i = 0; i < 5; i++) {
write(fd, msg, strlen(msg));
usleep(200);
}

wait(NULL);
close(fd);
}

return 0;
}

/*
Q: Write a program that opens a file (with the open() system call)
and then calls fork() to create a new process. Can both the child
and parent access the file descriptor returned by open()? What
happens when they are writing to the file concurrently, i.e., at the
same time?
A: the order in which the content will be written to the file is
undeterministic. I needed to introduce loops & delays to force the race
condition to happen, but it was clear
*/
42 changes: 42 additions & 0 deletions ostep/ex5_3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
int pipe_fds[2];
assert(pipe(pipe_fds) >= 0);

int pipe_read_fd = pipe_fds[0];
int pipe_write_fd = pipe_fds[1];

int rc = fork();
assert(rc >= 0);

if (rc == 0) {
sleep(2); // sleep to prove that nothing happens in parent until child
// writes to pipe
char* msg = "msg from child!";
write(pipe_write_fd, msg, strlen(msg));
} else {
char buffer[200];
printf("parent blocked on read() ...\n");
read(pipe_read_fd, buffer, 200);
printf("parent received: “%s”\n", buffer);
printf("parent terminating\n");
}

return 0;
}

/*
Q: Write another program using fork(). The child process should
print “hello”; the parent process should print “goodbye”. You should
try to ensure that the child process always prints first; can you do
this without calling wait() in the parent?
A: can be achieved using a pipe. parent blocks on read() until child writes to
it.
*/
74 changes: 74 additions & 0 deletions ostep/ex5_8.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
int status;

int pipe_fds[2];
assert(pipe(pipe_fds) >= 0);

int pipe_read_fd = pipe_fds[0];
int pipe_write_fd = pipe_fds[1];

pid_t rc1 = fork();
assert(rc1 >= 0);

if (rc1 == 0) {
char* out_buffer = "msg from child 1!";

printf("child 1 is writing...\n");
write(pipe_write_fd, out_buffer, strlen(out_buffer));

close(pipe_write_fd);
printf("child 1 terminating...\n");

exit(0);
}

pid_t rc2 = fork();
assert(rc2 >= 0);

if (rc2 == 0) {
printf("child 2 blocked on read()...\n");

char in_buffer[200];
read(pipe_read_fd, in_buffer, 200);
printf("child 2 finished reading...\n");

char out_buffer[400];
sprintf(out_buffer, "%s || msg from child 2!", in_buffer);

printf("child 2 is writing...\n");
write(pipe_write_fd, out_buffer, strlen(out_buffer));

close(pipe_write_fd);
printf("child 2 terminating...\n");

exit(0);
}

// Parent process

printf("parent waiting for child 1 (pid: %d) ...\n", rc1);
waitpid(rc1, &status, 0);
printf("parent waiting for child 2 (pid: %d) ...\n", rc1);
waitpid(rc2, &status, 0);

char buffer[200];
read(pipe_read_fd, buffer, 200);
printf("parent received: “%s”\n", buffer);

close(pipe_write_fd);
printf("parent terminating...\n");

return 0;
}

/*
Q: Write a program that creates two children, and connects the standard output
of one to the standard input of the other, using the pipe() system call.
*/
2 changes: 0 additions & 2 deletions sandbox/.gitignore

This file was deleted.

0 comments on commit 30d8433

Please sign in to comment.