week 6 lecture 1 nwen 241 system programming€¦ · week 6 lecture 1 nwen 241 system programming...
TRANSCRIPT
Content
• What are System calls
• Why do we need system calls
• Categories of System Calls
• System calls for Process Management
2
System calls - What and Why?
3
Conceptual View of a Computer System
Hardware
Applications
Operating System
Users
System calls - What and Why?
4
- Typically needs access to system resources.
- System resources can be:a) physical – e.g. input devices, screen displays.
ORb) Virtual – e.g. files, network connections, threads.
- Applications need O.S. to enable them access theseresources.
Conceptual View of a Computer System
Hardware
Applications
Operating System
Users
System calls - What and Why?
• Operating Systems do not allow application software toaccess system resources directly due to security andreliability issues.
• A program can request the services of system resources fromO.S through system calls.
• System calls are function invocations made fromapplication into the OS in order to request some service orresource from the operating system.
• Application developers often do not have direct access tosystem calls but can access them through a system call API,which in turn invokes the system call. 5
Hardware
Applications
Operating System
Users
System Call Interface
An example of a system call usage
• Consider the following example:
6
C Library function printf "asks" the operating system to print for the calling program by using the system call API routines
#include<stdio.h>
int main()
{
printf("Hello World");
return 0;
}
System call invocation –Example
7
#include <stdio.h>void main(void){
printf("Hello, world\n");exit(0);
}
System Call InterfaceUser mode
Kernel mode
Standard C Library
write()
sys_write()system call
The Complete picture• A system call is a call to a function that is a part of the kernel to request service
from the operating system.
• When a program needs to access system resources, it makes a system call anda context-switch between the user program and the kernel is performed.
8
User process executingCalls system
callReturn to user mode
Execute system call
Set mode bit =1 before switching to user mode
User mode(mode bit =1)
Kernel mode(mode bit =0)
TrapSet mode bit =0 before switching to kernel mode
How to know which system calls are invoked?
Two commands:
a) ltrace – traces call to library functions
b) strace -traces system calls
*Details in Linux manual pages :
- >Open terminal -> write man <command-name>
Example: man ltrace
*Usage : ltrace ./<program executable file>
ltrace –S ./<program executable file> (also display system calls)
9
10
#include<stdio.h>
int main()
{
printf(”Hello
World”) ;return 0;
}
hello.c
Compile
Run
Output
ltrace
ltrace
output
How to know which system calls are invoked?
11
strace output
How to know which system calls are invoked?
Invoking System callsThere are two different methods by which a programcan invoke system calls:
• Directly: by making a system call to a function (i.e.,entry point) built directly into the kernel, or
• Indirectly: by calling a higher-level library routine(provided by Linux system library and languagelibrary) that invokes the system call.
• The system calls and system libraries togetherconstitute the system call applicationprogramming interface (API).
Three most common APIs:- Win32 API for Windows- POSIX API for POSIX-based systems (includingUNIX, Linux, and Mac OS X)
- Java API for the Java virtual machine (JVM) 12
User Applications
System Libraries
System Call Interface
Direct system call
System call via API
Directly Invoking System calls
13
• To make a direct system call we need low-level programming, generallyin assembler. User need to know target architecture, cannot create CPUindependent code.
.global _start
.text_start:# write(1, message, 13)mov $1, %rax # system call 1 is to write mov $1, %rdi # file handle 1 is stdoutmov $message, %rsi # address of string to outputmov $13, %rdx # number of bytessyscall # invoke operating system to do the write.data
message:.ascii "Hello, world\n"
Tedious and machine dependent
14
User Space Kernel Space
main()
{
write(1,"Hello World",strlen("Hello World"));}
sys_write()
{
.
.
.
}
unistd.h
string.h
Invoking System calls through library routines
Categories of System calls
15
Categories and examples of system calls
16
• Unix and Linux both conform to POSIX standard (GNU C Library -glibc)
• POSIX: Portable Operating System Interface
Categories of System Calls
• File manipulation – ( create, delete, open, close)
• Process Control – (create, terminate)
• Device Management – ( request, release)
• Information Maintenance – (time, date, get / set system date)
• Communications – ( create , delete connection, receive, send message)
• Protection – ( create , delete connection, receive, send message)
17
What is a process ?
18
Program and process are related terms.
Program is a set of instructions to carry out a specified task
Process is a program in execution
Passive entity Active entity
Program is a stored in disk and does not require any other resource.
Process requires system resources such as CPU, memory, I/O etc.
Life span - Longer Life span – limited
Each time a program is run a new process is created.
Process in memory
19
Code Segment(Text Segment)
Data Segment
Heap Segment
free
Stack Segment
Text / Code Segment Contains program’s machine code
Segments for Data
spread over: Data Segment – Fixed space for global
variables and constants
Stack Segment – For temporary data, e.g., local variables in a function; expands / shrinks as program runs
Heap Segment – For dynamically allocatedmemory; expands / shrinks as program runs
Process lifecycle
20
As a process executes, it changes state
• new: The process is being created
• ready: The process is waiting to be assigned to a processor
• running: Instructions are being executed
• waiting: The process is waiting for some event to occur
• terminated: The process has finished execution
new
ready running
waiting
terminatedadmitted
interrupt
exit
I/O or event completion I/O or
event wait
Scheduler dispatch
Process control block
• Information associated with each process– Process state
– Program counter
– CPU registers
– CPU scheduling information
– Memory-management information
– Accounting information
– I/O status information
• A process is named using its process ID (PID) or process #
• Data is stored in a process control block (PCB)
21
Process switching
22
Process scheduling
• Process scheduler selects among ready processes for next execution on CPU
• Maintains scheduling queues of processes• Job queue – set of all processes in the system
• Ready queue – set of all processes residing in main memory, ready and waiting to execute
• Device queues – set of processes waiting for an I/O device
• Processes migrate among the various queues
23
Ready queue and various I/O device queues
24
Recap
• Program Vs Process
• PCB
• Process Switching
• Process Scheduler
25
Process management system calls
The following system calls are used for basic process management.
• fork()
• exec()
• wait()
• exit()
26
Defined in unistd.h
Defined in sys/wait.h
Defined in stdlib.h
Process Initialization on Linux
• The init process.
• A process is created by another process, which, in turn create other processes process tree
27
init
pid = 1
sshd
pid = 3028
login
pid = 8415kthreadd
pid = 2
sshd
pid = 3610
pdflush
pid = 200
khelper
pid = 6
tcsch
pid = 4005emacs
pid = 9204
bash
pid = 8416
ps
pid = 9298
Linux process tree
Every process has a process ID (PID)
Linux ps command
• Used to obtain information about processes that are running in the current shell
28
$ psPID TTY TIME CMD31843 pts/35 00:00:00 bash31850 pts/35 00:00:00 ps
Process IDEvery process is assigned a PID by the kernel
Linux ps command
29
$ ps -fUID PID PPID C STIME TTY TIME CMDsahnijy 31843 31835 0 12:37 pts/35 00:00:00 -bashsahnijy 32100 31843 0 12:43 pts/35 00:00:00 ps -f
Parent Process IDPID of the process that started the process
Parent and child
30
init
pid = 1
sshd
pid = 3028
login
pid = 8415kthreadd
pid = 2
sshd
pid = 3610
pdflush
pid = 200
khelper
pid = 6
tcsch
pid = 4005emacs
pid = 9204
bash
pid = 8416
ps
pid = 9298
Parent of processes 6 and 200,Child of process 1
Children of process 2
When liux starts it runs a singleprogram, init with process id 1
Process creation with fork()
In Linux all processes are created with the systemcall fork().
A process calling fork() spawns a new process(child), which is a copy of the calling process.
After a successful fork() call, two copies of theoriginal code will be running.
31
#include <sys/types.h> #include <unistd.h>
pid_t fork(void);
Parent
fork ()
Parent
Parent(Same
program statements)
Child(Same
program statements)
Process creation with fork()
After the fork(), both processes not only run the same program, but they resume execution as though both had called the system call.
fork() returns an integer value to both parent and child process.
32
fork ()
Unsuccessful Successful
Return -1 Return 0 Return PID of child
Parent Child
Illustration
33
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
Prior to fork() system call:
Illustration
34
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
After fork() system call:
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}13434p 0p
Illustration
35
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
After fork() system call:
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
In parent, fork() will return PID of child
13434p 0p
Illustration
36
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
After fork() system call:
void main(void){printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
In parent, fork() will return PID of childIn child, fork() will return 0
13434p 0p
Output (if fork() is successful)
37
void main(void){
printf("Before fork\n");pid_t p = fork();printf("p = %d\n", p);
}
Before forkp = 13424p = 0
Before fork
From parent (and the only process)
p = 13434 From parent
p = 0From new child
Order of appearance not predictable
Using the return value
38
void main(void){
printf("Before fork\n");pid_t p = fork();if(p < 0) {
/* Failed to fork */} else if(p == 0) {
/* Child process will execute this part */} else if(p > 0){
/* Parent process will execute this part */}
}
Can use return value to determine what to do in parent and child
Process ID
39
To obtain the process ID of a process:
pid_t getpid(void);
void main(void){
pid_t p = fork();if(p == 0) { /* Child */
printf("My PID: %d\n", getpid());} else if(p > 0) { /* Parent */
printf("My PID: %d, child PID: %d\n", getpid(), p);}
}
Variables
40
After a successful fork() call, two copies of the original code will be running
Parent and child will have their own copies of variables
Variable changes in one process will not affect the variables in the other process
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
41
Prior to fork() system call:
10
20
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
42
After fork() system call:
10
20
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
} 10
20
ab
13434p 0p
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
43
After fork() system call:
10
21
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
} 11
20
ab
13434p 0p
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
44
After fork() system call:
10
21
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
} 11
20
ab
13434p 0p
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
45
After fork() system call:
10
21
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
} 11
20
ab
10 2111 20
13434p 0p
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
}
Illustration
46
After fork() system call:
10
21
ab
void main(void){
int a = 10, b = 20;pid_t p = fork();if(p < 0) { /* Failed */exit(0);
} else if(p == 0) { /* Child */a++;
} else { /* Parent */b++;
}printf("%d %d\n", a, b);
} 11
20
ab
11 2010 21
13434p 0p
Fork bomb
47
void main(void){
while(1)fork();
}
What will happen in this code?
Fork bomb (aka wabbit or rabbit virus): a form of denial of service attack to Linux based systems
Process creation with exec()
exec() call replaces a current process’ image with a new one (i.e. loadsa new program within current process)
Upon success, exec() does not return to the caller If it does return, it means the call failed. Typical reasons are: non-existent file (bad
path) or bad permissions.
The process id PID is not changed, this is because we are not creating anew process we are just replacing a process with another process
The new process is executed from the entry point.
48
Process creation with exec()
There is no system call specifically by the name exec() By exec() we usually refer to a family of calls:
int execl(char *path, char *arg, ...); int execv(char *path, char *argv[]); int execle(char *path, char *arg, ...,
char *envp[]); int execve(char *path, char *argv[],
char *envp[]); int execlp(char *file, char *arg, ...); int execvp(char *file, char *argv[]);
The various options l, v, e, and p mean: l : an argument list, v : an argument vector, e : an environment vector, and p: a search path.
49
Illustration
50
void main(void){printf("Before exec\n");int r = execl("/bin/ls", "ls", NULL);printf("r = %d\n", r);
}
int execl(char *path, char *arg, ...);
List of one or more pointers of argument list to the program to be executed. End with NULL pointer
Path of the executable binary
Illustration
51
void main(void){printf("Before exec\n");int r = execl("/bin/ls", "ls", NULL);printf("r = %d\n", r);
}
int execl(char *path, char *arg, ...);
List of one or more pointers of argument list to the program to be executed. End with NULL pointer
Path of the executable binary
Illustration
52
void main(void){printf("Before exec\n");int r = execl("/bin/ls", "ls", NULL);printf("r = %d\n", r);
}
int execl(char *path, char *arg, ...);
List of one or more pointers of argument list to the program to be executed. End with NULL pointer
Path of the executable binary
Illustration
53
After exec() system call:
Image will be replaced with /bin/ls
/bin/ls program
Before exec01_Prog1.c 01_Prog1 02_Prog2.c 02_Prog2
What parent does while the child is executing ??
54
init
pid = 1
sshd
pid = 3028
login
pid = 8415kthreadd
pid = 2
sshd
pid = 3610
pdflush
pid = 200
khelper
pid = 6
tcsch
pid = 4005emacs
pid = 9204
bash
pid = 8416
ps
pid = 9298
• execute in parallel
• wait for child to finish
fork() and exec() together
Often after doing fork()we want to load a new program into the child.
Most common e.g. a shell programs
55
PID=28
p1
PID=28
p1
PID=34
c1
fork()
PID=34
c1
PID=34
c1
exec(ls)
tcsh ls
wait() System Call
56
Forces the parent to suspend execution, i.e. wait for the child to terminate.
When the child process terminates, it returns a termination status to theoperating system, which is then returned to the waiting parent process if thestatus is not NULL. The status can be then be analyzed by the parent.
The return value is:
PID of the exited process, if no error
(-1) if an error has happened
#include<unistd.h>#include<sys/wait.h>
pid_t wait(int *status);
Example
57
void main(void){
printf("Before fork\n");int p = fork();if(p < 0) { /* Failed to fork */
exit(0);} else if(p == 0) { /* Child process */
printf("p = %d\n", p);} else { /* Parent process */
wait(NULL);}
}
58
Example of wait when forking separate
process#include<unistd.h>#include<sys/wait.h> #include<stdio.h>
int main(void){
pid_t pid;/* fork a child process */pid=fork();
if(pid<0){printf("Error");return 1; }
else if(pid==0){ /*child process */execlp("/bin/ls","ls", NULL); }
else{/*Parent process waits for child process to complete*/wait(NULL);printf("Child Completes"); }
}
01_Prog1.c 01_Prog1 02_Prog2.c 02_Prog2Child Completes
exit() System Call
59
A process can either terminate normally or abnormally (e.g. divide by zeroerror).
exit( ) system call enables explicit call for normal termination andgracefully terminates process execution (it does clean up and release ofresources).
void exit(int status);
The status argument given to exit() defines the termination status of theprocess. It is an integer value between 0 and 255.
By convention, when a process exits with a status of zero that means itterminated normally and didn’t encounter any problems; when a process exitwith a non-zero status that means it did have problems.
Example of wait() and exit()
60
main(){
int pid; int rv;
pid=fork();switch(pid){
case -1:printf("Error -- Something went wrong with fork()\n");exit(1); // parent exits
case 0:printf("CHILD: This is the child process!\n");printf("CHILD: My PID is %d\n", getpid());printf("CHILD: Enter my exit status: ");scanf(" %d", &rv);printf("CHILD: I'm outta here!\n");exit(rv);
default:printf("PARENT: This is the parent process!\n");printf("PARENT: My child's PID is %d\n", pid);printf("PARENT: I'm now waiting for my child to exit()...\n");wait(&rv); printf("PARENT: I'm outta here!\n");
}}
Next lecture
• Interprocess Communication
61