Friday, June 09, 2006 “I think there is a world market for maybe five computers”. - Thomas Watson, Chairman of IBM, 1943
Download
Report
Transcript Friday, June 09, 2006 “I think there is a world market for maybe five computers”. - Thomas Watson, Chairman of IBM, 1943
Friday, June 09, 2006
“I think there is a world market for
maybe five computers”.
- Thomas Watson, Chairman of IBM, 1943
System Calls
Example :
UNIX read system call
Highly machine dependant (Assembly code)
We can make system calls through C program
using library procedures.
System Calls
UNIX has an almost 1-1 relationship
between system calls and library procedures
open
read
write
close
POSIX defines about 100 procedure calls
Library procedures:
A procedure call may itself make a system
call
e.g.
fopen
malloc
In Windows the library calls and actual
system calls are decoupled
Win32 API calls number in thousands.
Large number of calls or managing
windows, menus, scroll bars, dialog boxes,
fonts, text…
Not very clear which are system calls and
which are user-space library calls
Process Management
fork creates a new process in Unix
It creates an exact duplicate of the
original parent process including file
descriptors, registers, etc (everything)
All variables have identical values at the
time of fork
Remember: Parent’s data is copied
Subsequent changes do not affect each other
Process Management
int pid = fork();
pid contains zero in child process
pid contains the process id of child in
parent
int main(void){
int counter=0, i, statloc, pid;
pid=fork();
if (pid==-1){
perror("fork");
exit(1);
}
else if (pid==0){
counter=100;
for(i=0;i<5; i++){
printf("Child counter is %d\n", counter);
counter++;
sleep(2);
}
}
else {
counter=500;
for(i=0;i<5; i++){
printf("Parent counter is %d\n", counter);
counter++;
sleep(2);
}
waitpid(pid, &statloc, 0);
}
return 0;
}
One Possible Output
Parent counter is 500
Child counter is 100
Child counter is 101
Parent counter is 501
Parent counter is 502
Child counter is 102
Child counter is 103
Parent counter is 503
Parent counter is 504
Child counter is 104
Another possible output
Parent counter is 500
Child counter is 100
Child counter is 101
Parent counter is 501
Parent counter is 502
Child counter is 102
Parent counter is 503
Child counter is 103
Child counter is 104
Parent counter is 504
sleep
suspends execution for an interval
waitpid
can wait for a specific child or any
child by setting first parameter to -1
man sleep
int main(void){
int counter=0, i, statloc, pid;
pid=fork();
if (pid==-1){
perror("fork");
exit(1);
}
else if (pid==0){
counter=100;
for(i=0;i<5; i++){
printf("Child counter is %d\n", counter);
counter++;
sleep(2);
}
}
else {
waitpid(pid, &statloc, 0);
counter=500;
for(i=0;i<5; i++){
printf("Parent counter is %d\n",counter);
counter++;
sleep(2);
}
}
return 0;
}
Child counter is 100
Child counter is 101
Child counter is 102
Child counter is 103
Child counter is 104
Parent counter is 500
Parent counter is 501
Parent counter is 502
Parent counter is 503
Parent counter is 504
int main(void){
int i;
int* counter;
int pid;
counter=(int*) malloc(sizeof(int));
pid=fork();
if (pid==-1){
perror("fork");
exit(1);
}
else if (pid==0){
*counter=100;
for(i=0;i<5; i++){
printf("Child counter is %d\n", *counter)
(*counter)++;
sleep(2);
}
else {
*counter=500;
for(i=0;i<5; i++){
printf("Parent counter is %d\n",*counter);
(*counter)++;
sleep(2);
}
waitpid(pid, &statloc, 0);
}
return 0;
}
One Possible Output
Parent counter is 500
Child counter is 100
Child counter is 101
Parent counter is 501
Parent counter is 502
Child counter is 102
Child counter is 103
Parent counter is 503
Parent counter is 504
Child counter is 104
exec system call replaces the current
process image with a new process
image.
int main(int argc, char *argv[])
{
int i;
int pid;
int child_status;
pid = fork();
if (pid<0){
printf("Fork Failed");
exit(-1);
}
else if (pid==0){
printf("Child first line\n");
execlp("/bin/ls","ls",”-l”,NULL);
}
else {
wait(&child_status);
printf("Child Complete\n");
}
return 0;
}
Output
Child first line
-rwxr-xr-x 1 username group
-rw-r--r-- 1 username group
-rw-r--r-- 1 username group
-rw-r--r-- 1 username group
-rw-r--r-- 1 username group
Child Complete
9203 Jun 4 09:43 fork-ex
348 Jun 4 09:43 fork-ex.c
355 May 6 14:44 ex1.c
657 May 6 17:13 ex2.c
657 May 6 17:00 ex3.c
int main(int argc, char *argv[]){
int i, pid, pid2;
int child_status;
pid = fork();
if (pid==0){
pid2=fork();
if (pid2==0){
printf("%d GChild first line\n", getpid());
}
else{
printf("%d Child first line\n", getpid());
waitpid(pid2, &child_status, 0);
}
}
else {
printf("%d Parent first line\n", getpid());
waitpid(pid, &child_status, 0);
}
return 0;}
One Possible Output
13242 GChild first line
13240 Parent first line
13241 Child first line
Another Possible Output
13243 Parent first line
13244 Child first line
13245 GChild first line
int main(int argc, char *argv[]){
int pid;
int child_status;
pid = fork();
if (pid<0){
printf("Fork Failed");
exit(-1);
}
else if (pid==0){
printf("Child first line\n");
execlp("/bin/cal","cal",NULL);
//what happens here?
printf("Child second line\n");
printf("Child third line\n");
}
else {
//what if we move wait statement down?
wait(&child_status);
printf("Parent line 1\n");
printf("Parent line 2\n");
printf("Parent line 3\n");
}
return 0;
}
OUTPUT
Child first line
June 2006
S M Tu W Th F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
Parent line 1
Parent line 2
Parent line 3
Simple shell
while(1) {
type_prompt();
read_command(command, parameters);
if (fork()!=0){
waitpid(-1, &status, 0);
}
else {
exec(command, parameters, 0);
}
}
Signals
Notification sent to a process in order to
notify it of important events.
Each signal has an integer number (as well
as symbolic name) that represents it
Signals
Why signals?
int main(int argc, char *argv[])
{
int pid;
int i;
signal(SIGCHLD, catch_child);
pid=fork();
if (pid==0){
execlp("/bin/ls", "ls", NULL);
}
for (i=0; i<10; i++){
printf("%d\n", i);
sleep(1);
}
return 0;
}
void catch_child(int sig_num)
{
int child_status;
wait(&child_status);
printf("child exited with code %d\n", child_status);
}
int main(int argc, char *argv[])
{
int i;
int pid, pid2, pid3;
int child_status;
pid = fork();
//pid contains zero for child process
if (pid==0){
pid2=fork();
if (pid2==0){
printf("hello");
}
else{
printf("there");
wait(&child_status);
}
}
else {
pid3=fork();
if (pid3==0){
printf("Good");
}
else{
printf("Luck");
wait(&child_status);
}
}
return 0;
}
Process Termination
Last instruction
exit() system call
After fork() call:
The child process inherits all files that
were open in the parent process. If one of
them reads from such an open file, the
read/write pointer is advanced for both of
them.
If one process closes a shared file, it is still
kept open in the other process.
Files opened after the call to fork() are not
shared by both processes.
Ctrl-C SIGINT
Ctrl-Z SIGTSTP
Default signal handlers
SIGSEGV – Segmentation violation – Core
dumped
Comparison
System Calls for I/O
5 basic UNIX system calls for file I/O
open
close
read
write
lseek
Different from regular procedure calls.
How?
open System Call
open ( path, mode flags)
int fd = open("/dir1/file1", O_RDONLY);
int fd = open("/dir1/file1", O_WRONLY | O_APPEND);
System Calls for I/O
Every process in Unix starts out with three
file descriptors
file descriptor 0 is standard input
file descriptor 1 is standard output
file descriptor 2 is standard error
read(0, …) //read from standard input
write(1, …) //write to standard output
open System Call
O_RDONLY
Open the file in read-only mode.
O_WRONLY
Open the file in write-only mode.
O_RDWR
Open the file for both reading and writing.
In addition, any of the following flags may be
OR-ed with the mode flag:
O_CREAT
If the file does not exist already - create it.
open System Call
O_EXCL
If used together with O_CREAT, the call
will fail if the file already exists.
O_TRUNC
If the file already exists, truncate it (i.e. erase its
contents).
O_APPEND
Open the file in append mode. Any data written to the file is
appended at the end of the file.
close System Call
close (filedescriptor)
if (close(fd) == -1) {
perror("close");
exit(1);
}
read System Call
int num_read = read(filedescriptor, buffer, nbytes);
num_read == 0 ?
num_read < 0 ?
write System Call
int num = write(filedescriptor, buffer, nbytes);
num < 0 ?
File permissions
access( “/dir1/file1”, R_OK) ==0
read access granted
access( “/dir1/file1”, R_OK | W_OK ) ==0
read/ write access granted
R_OK Test for read permission.
W_OK Test for write permission.
X_OK Test for execute or search permission.
F_OK Check existence of file
File permissions
chmod( “/dir1/file1”, S_IRGRP)
execlp("/bin/ls","ls","-l",”..”, NULL);
man -s 2 read
man –a read
gcc -g -Wall fork-ex.c -o fork-ex
It is good practice to always use the -Wall option
ps -ef | grep yourusername
ps -ef | grep init
cat filea fileb filec | sort > /dev/lp &
lseek System Call
Practice Homework
int num = lseek( filedescriptor, offset, whence);
num < 0 ?
open System Call
Practice Homework
S_IRWXU
Owner of the file has read, write and execute
permissions to the file.
S_IRUSR
Owner of the file has read permission to the file.
S_IWUSR
Owner of the file has write permission to the file.
S_IXUSR
Owner of the file has execute permission to the file.
open System Call
Practice Homework
S_IRWXG
Group of the file has read,write and execute
permissions to the file.
S_IRGRP
Group of the file has read permission to the file.
S_IWGRP
Group of the file has write permission to the file.
S_IXGRP
Group of the file has execute permission to the file.
open System Call
Practice Homework
S_IRWXO
Other users have read,write and execute permissions to
the file.
S_IROTH
Other users have read permission to the file.
S_IWOTH
Other users have write permission to the file.
S_IXOTH
Other users have execute permission to the file.
Directories
Practice Homework
#include <dirent.h>
/* open the directory for reading. */
DIR* dir = opendir("/dir1/subdir2/");
if (!dir) {
perror("opendir");
exit(1);
}
if (closedir(dir) == -1) { perror("closedir");
exit(1); }
Directories
Practice Homework
struct dirent* entry;
while ( (entry = readdir(dir)) != NULL)
{
printf("%s\n", entry->d_name);
}
void function(DIR* dirp, char* dir_path){
struct dirent* dir_entry;
char* full_path;
while ( (dir_entry = readdir(dirp)) != NULL) {
if (strcmp(dir_entry->d_name, ".") == 0)
continue;
if (strcmp(dir_entry->d_name, "..") == 0)
continue;
full_path=(char*)malloc(strlen(dir_path)
+strlen(dir_entry->d_name)+1);
strcpy(full_path, dir_path);
strcat(full_path, dir_entry->d_name);
printf("dir_entry->d_name = %s\n",dir_entry->d_name);
if (access(full_path, R_OK) == -1) {
printf("read permission to file denied.\n");
return;
}
free(full_path);
Practice Homework
}
}
File status
Practice Homework
struct stat file_status
stat( “/dir1/file1”, &file_status)
if (S_ISDIR(file_status.stmode))
if (S_ISFIFO(file_status.stmode))