CS 111 Notes for Lecture 1/20


Intro


Fork

Fork clones a process - with a few key differences between the processes:
  1. Two processes have different process IDs, and you use getpid() to get the child’s pid
  2. getppid(void) gets the parent's pid
  3. The child gets its own copy of file descriptor tables
  4. The child has its own CPU time info
  5. Only one process will get a pending signal
  6. File locks (eggert advises us to use these) - these are optional. If processes cooperate, it will work fine. But a process like the shell will ignore all file locks.

Execvp

The syntax for execvp is : execvp(char* const, char* const)
Execvp is almost the opposite of fork() :



The following method is an combination of fork and execvp, and it may be easier as well as a better alternative:




What does *restrict do?

Restrict makes sure that pointers point to different parts of memory. This keeps allocated memory from interfering with allocated memory of a different variable or pointer. It is used in:





ASIDE :

But, this was part of posix because programmers were afraid of poor performance- say you copied 8GB and you need only a bit, posix will let it be fast. fork() is expensive whereas posix is cheap.

ORTHOGONALITY :

In math : independent 90 degree axes. Choosing a dimension(x_0, y_0, z_0), you’ll get a point. choice of an attribute doesn’t effect anything else.
We want to have a similar definition for CS is terms of processes and files running "orthogonally".

In a computer, we find processes and files. Files are slow, unreliable and nonrobust. We want performance and orthogonality for them. We can split files into two categories:

Network, mouse, keyboard :

vs

Flash/Disk


UNIX's big idea: call both kinds of devices the same thing.

files-> open, close, read, write, dup2, lseek, locking.



You can say :


What happens if you try to pass a stream device to lseek?

It will return -1 and set errno to 0. This is because lseek needs to move the fd with a certain offset, but with data coming from a stream like the keyboard, this has no limit.

Exceptions happen when primitives are set to files. This may minimize the number of primitives.

Processes communicate to files, and other processes. This is called Interprocess Communication (IPC)

This is what pipes are for :

Bounded pipes work because if you write to it and it is full, kernel will just make you wait.

This:

can be written in shell as: (A & B) | (C & D & E)

Downfalls

There is no way to send this message to just the process you create. This setup is not often done because of this.
This can be a problem in sort.c. say you want to make a temporary file:


If people are trying to read their own files, this will mess up.
Instead, create a buffer file before opening:


Now, open (name, ...) will set different names. But this is voluntary – processes could overwrite the names if they aren’t "nice()". You can fix this with: O_EXCL... But it will fail if the same file name is found.

Instead, you should do a while loop and put a random number in the temp file. Then leave the loop if it is original (if open succeeds).


Between the two opens there exist a race condition because one file might might be trying to open the file for reading while the other might be opening the file for writing.

You don’t want orthogonality here because in the earlier example of posix, you only affect the child. Here, it is a correctness issue, this affects other stuff outside the child process.