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))