A first view of processes in
Linux
1
Objectives
• Understand the concept of a process vs a program
• Get a first understanding of the kernel view of a process
• Know a few tools to investigate process information
• Learn how to create your own processes from a C program
• Learn to write a simple shell!
Note: All the program examples shown here are in the github under the proc/ directory
2
First concepts Experiment ( here loopy.c is just a sample program)
Concepts Source Create a small program (loopy.c)
• Programs are what are written,
compiled, etc etc.
• Processes are what get executed Compile
and create
Create the executable (and/or .o) file
• System calls are the interface for a
process to access OS functionality
$ hexdump –cx loopy
Use ls to see the files Use ps to see your Examine $ ldd loopy
in the directory: processes: the files: $ objdump [-hd] loopy
$ ls $ ps $ objdump -d libc.so… | grep syscall
loopy.c PID TTY TIME CMD
loopy 2269 pts/0 00:00:00 bash
3303 pts/0 00:00:12 loopy Examine $ ltrace -x ‘@libc.so*’ loopy busy
3321 pts/0 00:00:00 ps the $ strace loopy busy
execution $ gdb loopy 3
The kernel’s information about a process
• Every process has a Process ID – PID see ps(1) getpid(2)
• Along with a process is associated a bunch of things
• Memory - Text, data, stack, heap
• Its owner (user), its parent(process), its children(processes)
• Its resources – associated memory, files, sockets, other resources
• Its execution state (Instruction pointer, register values)
• The code it is executing (like a.out or /bin/ls)
• All this info is maintained by the kernel for each process – Process Control
Block (PCB)
• Kernel creates, updates, deletes PCBs. Uses it for CPU scheduling, memory
allocation, IO scheduling, access control to resources, etc.
4
Three basic process system calls
fork() , exec() and wait()
5
Creating processes programmatically
• All process are created from an initial process: see pstree(1)
• This happens by using a technique consisting of two building blocks
• A process can simply replicate itself creating a new process which is almost
identical but with a new process id (of course) (new box)
• A process can simply remain the same id but the program executing is new,
ie the pid remains the same. (change colour)
1 1 1 1 1 1 1
4 Fork – Create a duplicate
i.e., one new process
Notice:
pstree -p
2
3 ... 3 3
Exec – repurpose the same
Time 0 1 2 3 4 5 6
4
time
1 1 1
4
Linux system calls to create processes
3
• On UNIX/ Linux you can explicitly create your own processes using the techniques
mentioned.
• All processes are in RAM, all these replication/overlaying happens in the RAM
• For this there are two useful system calls fork() and often execv():
• fork() simply creates a new process which is a duplicate process. So we end
up with an additional new process which is nearly identical to the calling process.
• Of course they are two separate processes so they have separate PIDs (separate
data/stack/variables etc – almost nothing shared).
• Also there is a quick way to tell which one was the original(parent) and which
was the new one(child). (return value of fork())
• Quick example follows
7
Linux process – fork() – ing off a new process
6376
int i=500; printf(“The Beginning\n”); x is 0
x = fork();
printf(“Hello world\n”); 6375 6375
x is
if ( x == 0) x is ?
6376
printf("I am child\n); time
else Before After
printf("I am parent of fork() call
process: %d", x );
printf(“The End\n”);
8
What is printed in the following
3170 3171
x i x i
int x; int i=500; ? 500
3171 500 0 500
x = fork();
A A
printf(“A\n”);
if ( x == 0) {
Of course, the process has 0 501
i++; actually the executable
B
printf(“B\n”); version of this code!
} else { 3171 499
i--; C
printf(“C\n”);
499 501
}
printf(“%d\n”,i);
Summary: the variables for x and i of the child are completely independent from (not shared with) the parent:
9
that is obvious since processes are isolated!
Linux processes – replacing code of an
existing process with execv()
char * prog = "/bin/ls";
6375 6375
char * params[] = {"/bin/ls", a.out /bin/ls
“/bin/ls”
"-l", "/home", NULL};
printf("The Beginning\n"); time
printf(“pid=%d\n”,getpid()); Before After
execv(prog, params); exec() call
X
printf(“pid=%d\n”,getpid());
printf("The End\n");
Not a new process, so pid is the same
1. Check man exec and
and notice execv, execvp in addition to other variations.
10
What is printed 3170
i prog params
int i; char * prog = "/bin/ls";
char * params[] = {"/bin/ls", ? [,,,NULL]
"-l", "/home", NULL};
for(i=0; i < 2 ; i++) { 0 [,,,NULL]
printf("B\n"); B
printf(“%d\n”, getpid()); 3170
execv(prog, params);
}
printf("E\n");
11
What is printed 3170
i prog params
Thei;
int earlier
charcode*(entire
proguser
= address space) is replaced by
"/bin/ls"; that
? of the
given[,,,NULL]
executable.
No way to access data and code of the program before exec was called.
char * params[] = {"/bin/ls",
"-l", "/home", NULL};
for(int i=0; i < 2 ; i++) {
/bin/ls -l
printf("B\n"); total 47 B
-rwxrwx--- 1 root vboxsf 1735 Feb 18 202
printf(“%d\n”, getpid()); 3170
-rwxrwx--- 1 root vboxsf 395 Jan 1 15:4
execv(prog, params); ..
..
} ..
printf("E\n");
12
Waiting for a child process to exit
• wait(2) tells the parent about int i=500; printf(“The Beginning\n”);
when/how a child x = fork();
(i.e., created by fork()) exited. printf(“Hello world\n”);
• It is usually used to wait until a if ( x == 0) {
child finishes executing. printf("I am child\n);
• In the simple form: getchar(); // child waits for user input
wait(int } else {
*wstatus); printf("I am parent of
• Another form: process: %d\n", x );
wait(int pid, wait(&wstat);//parent awaits child
int *wstatus, }
int options); printf(“The End\n”);
13
Check your understanding
• See: simple_fork.c simple_exec.c
• Howmany processes are created when the following code is run:
1 printf(”A\n”);
p1
2 fork();
3 printf(”B\n”); @2 @4
p2 p3
4 fork();
5 printf(”C\n”); @4
p4
14
Prelude to writing your own: What is shell ?
• A shell simply receives input from the
~$ ls
user and runs the corresponding program
• It also takes care of piping and I/O
redirection:
• date | tr [:lower:] [:upper:] > outfile
• It also has some builtin commands like
The $ is called the shell prompt.
You can change it using the environment
setting some environment variable values,
variable PS1 like this: cd, alias, source, exit etc.
$ PS1=‘c:> ‘
just for fun.
While the common shell is bash (see ps),
there is also sh, csh, ksh etc.
15
3617
shell
How a shell can be built $ date fork()
3618
wait() exec() /bin/date
waiting
waiting 3618
$ ./myshell /bin/date
waiting
* /bin/date exit
Monday 03 January …
* /bin/du -s . $ du -s .
fork()
317 . 3619
wait()
* /bin/echo hi waiting
hi exec() /bin/du -s .
waiting
* exit waiting
$ ... /bin/du -s
3619
$ exit
$ .. And so on
$ .. And on until..
See shell.c “exit” is the command
$ exit
16
Summary
We learnt fork exec and wait system calls
We learnt that exec is actually a family of system calls
17
Things to do and understand
• Learn to use man pages – eg, which man page section has system calls. Diff
between man write and man 2 write
• Investigate the ps command, also check pstree command and
understand notions of parent and child processes.
• Investigating files:
• Use od –cx to see the contents of an a.out file
• See the code/data/stack segment in a program – use gdb or objdump
• Use strace and ltrace to see what system calls are called from your
executable
• Use fork() and exec() together to run simple programs
• Write a very simple shell – like shown in class
18
Things to do and understand
• Learn some helpful system calls (Build your repertoire)
• exec() family of calls – its not one call.
• fork()
• exit()
• sleep()
19
END
20