Lecture 2 - Review of Systems Programming, Malloc

Just note that the deadline for the class shouldn't be taken lightly. Do it early plz thx. But you are given 3 free days to use as a late day to submit late. There's no penalty for using them, and no penalty for saving them to the end of the quarter.

Quick Review of pipe

All a pipe is two file descriptors connected by a buffer. For lab 01 we are trying to do:

ls | sort -r

Manually in main() via two children who have to communicate with each other (three processes). ls is the upstream one, sort -r downstream. The OS will synchronize them.

Say sort -r tries to read from the pipe. The OS will say 'wait' until ls has written something to it. ls will drain the buffer, then wait. sort -r will add more, ...

When the pipe goes empty, there's no one who can write to it. sort -r will get EOF and goes away. But the parent needs to know when that process is done to orchestrate everything.

Doing it Practically

Say we start out with our parent process:

When you fork, the file descriptors are copied to the child. So if you pipe and then fork, both have synchronized file descriptors.

But we need to use dup2 system call to make the input stdin and output stdin for our certain processes:

But the problem is we need to close the extra fd's. Namely the child 2's pipe-out, and child 1's pipe in, and the paren't pipe in and out. We should get:

Eventually the `sort` process should terminate (but before close the input end of the pipe), then the `ls` process knows that it is done so it can close and terminate. Then the parent can be done!
Warning

DON'T FORGET to close the fd's for the parent!

malloc!

Remember our buddy malloc()! Here's the definitions:

void *malloc(size_t size);
void *calloc(size_t num, size_t size); // will just call malloc after multiplying the size and num params
void *free(void* ptr);
void *realloc(void *ptr, size_t size); // good for copying data. Frees ptr tho!

Usually size_t is a multiple of 16 so that it works with the cache-line of the system.

You're going to want to setup a linked list to organize the address ranges to see if it's alloced or not.

No printf()

Be wary that printf() will use malloc, so if you're using it you cannot use it to debug. Instead, at pn_cs453/Given/Asgn1 there's a debugger to help you. Other than that just use gdb.

Recall our format of memory is:

Here if you use sbrk then it moves the top pointer of the data segment. Namely, if you call it then you 'magically' create that space. However, if you want to move sbrk 2 bytes that's a bad idea! Instead you want to increment it in various page lengths, just some smallest hunk.

The space we increment is brand new memory, but we need to have the data structure in that page. What will help is to put a struct header at the top bytes of the page:

You can get the next struct's data pointer by just adding the size in bytes to the current structure.

Note

In the assignment notes you can use intptr_t.h and uintptr_t.h to help do some of this arithmetic for you, rather than having to consider the type of the pointer and namely its size.

What should the struct have?

Make sure that you use some static global pointer to be the root of the LL, so that you can traverse the whole list. If you need more space you move sbrk until you don't need more room.

What happens if sbrk says no and doesn't move? You need your calls to return NULL and set errno to the right error code. For instance ENOMEM seen in errno.h.

Using sbrk

Here's an example of using sbrk() calls:

#define PAGE_SIE 65536
sbrk(PAGE_SIZE);
h->next->size += PAGE_SIZE;
// ...

Write a display of our LL

It'll help to have a function that iterates through all the LL nodes and then either printf() or do something else with it to get information when debugging.

Libraries

The process of compilation is:

  1. Turn all *.c into relevant *.o files via gcc or similar.
  2. Use ld to link all the static libraries (see below)
  3. When running, relevant dynamic libraries are used.

Static Libraries are libraries that are linked at link time (*.a). A dynamic library aren't linked until you actually run the program (*.so).

Note

You need to make sure that you don't include lib C, otherwise you'll use the already used malloc(). Add a print statement or something in your malloc() such that you know its running yours!