+ All Categories
Home > Documents > Unix System Programming

Unix System Programming

Date post: 01-Jan-2016
Category:
Upload: damon-meadows
View: 46 times
Download: 0 times
Share this document with a friend
Description:
Unix System Programming. Chung-Ta King Department of Computer Science National Tsing Hua University. Outline. UNIX system programming IPC with shared memory IPC with message passing. Layers of the Unix. ( system calls: entries to kernel; facilities provided by OS). Processes. - PowerPoint PPT Presentation
49
Unix System Programming Chung-Ta King Department of Computer Science National Tsing Hua University
Transcript
Page 1: Unix System Programming

Unix System Programming

Chung-Ta KingDepartment of Computer ScienceNational Tsing Hua University

Page 2: Unix System Programming

2

Outline

UNIX system programming IPC with shared memory IPC with message passing

Page 3: Unix System Programming

3

Layers of the Unix

Users

Shells and commands

System calls

SignalsI PC

Networking

File systemI / O system

Device drivers

CPU schedulingDemand paging

Process managing

Machine hardware

(system calls: entries to kernel; facilities provided by OS)

Page 4: Unix System Programming

4

Processes

A process is a program in execution

Ethernet

Printer

Disk

Terminal

swapper

lpd

init

inetdgetty

csh ls ps

Page 5: Unix System Programming

5

Low-level Process I/O

All communication of a process with outside is done by reading or writing files => a single interface

File descriptor A non-negative integer for reference to a file Three descriptors are created at process creation: stdin

(0), stdout (1), stderr (2)all are connected to the terminal by default

More descriptors can be created with proper system calls: fd = open(“outfile”, O_WRONLY, 0644);

Descriptor table: there is limit on # of open files (20) Related system calls: read, write, open, creat, close,

unlink, lseek, dup, dup2

Page 6: Unix System Programming

6

Low-level Process I/O: Example

/* copy f1 to f2 */int f1,f2,n;if ((f1=open(arg[1],O_RDONLY)) == -1) /* error if non-exist */ error(“can’t open %s”, argv[1]);if ((f2 = creat(argv[2],0644)) == -1) error(“can’t create %s”,argv[2]);while ((n = read(f1,buf,BUFSIZ)) > 0) /* return: 0 -> EOF; -1 -> error; n < BUFSIZ -> OK (read will return upto end of line) */ if (write(f2,buf,n) != n) error(“write error”, (char *) 0);

Page 7: Unix System Programming

7

Process Creation

Switch to another program: execlp("/usr/ucb/rsh","rsh",”cs20","date",0); replaces current process image with a new image

Split a process: fork() and wait() fork() produces two identical processes; the child process

returns 0 and parent returns child pid if (fork() == 0)

execlp ("sh","sh",”-c",commandline,(char *) 0); Shell operation:

repeat get next command fork a child to run the command (fork() & execlp();) wait for the child to terminate (wait();)

Page 8: Unix System Programming

8

Examine Process Status

ps -ajl F UID PID PPID PRI SIZE RSS ... STAT TTY TIME COMMAND 100 0 1 0 0 780 164 S ? 0:20 init [3] 40 0 2 1 0 0 0 SW ? 0:00 (kflushd) 40 0 3 1 -12 0 0 SW< ? 0:00 (kswapd) 40 0 4 1 0 0 0 SW ? 0:00 (nfsiod) 40 0 5 1 0 0 0 SW ? 0:00 (nfsiod) 140 0 12 1 0 756 100 S ? 0:20 /sbin/update 140 0 13 1 0 768 132 S ? 0:00 /sbin/kernel 100 0 67 1 0 772 112 S 2 0:00 (agetty)100000 1000 28413 28410 0 1992 696 S 1 0:00 /usr/lib/X11 100 1000 28424 28419 0 0 1232 S p0 0:00 -bin/tcsh 100 519 32452 32451 9 0 1188 S p1 0:00 -tcsh100000 519 32459 32452 12 0 852 R p1 0:00 ps -ajl

Page 9: Unix System Programming

9

Processes and Descriptors

fd = open("outfile",01002,0644);dup2(fd,1); /* dup fd to 1 => 1 now link to file */if (fork() == 0) /* the child */ execlp("/usr/ucb/rsh","rsh",”cs20","date",0);else { /* the parent */ fprint(stderr,”child working …\n”); wait(&status); system("ps -ajl"); tty = open(“/dev/tty”,2); write(tty,“done!”,5); }

Page 10: Unix System Programming

01

2ex1 open()

01

2ex1 3

01

2ex1 3

01

2ex1 |rsh 3

01

2ex1 3

system()

01

2csh 3

01

2ps 3

outfile

dup2()

fork()

fork()

01

2date

cs20

cs21

Page 11: Unix System Programming

11

Signals

When an external event of concern occurs, a signal is sent to all processes that were started from the same terminal and terminates them by default

signal(): alters the default action on a signal signal(SIGINT, SIG_IGN); signal(SIGINT, handle_int); signal() returns previous value of the signal and

resets to default action setjmp() and longjmp():

Page 12: Unix System Programming

12

Signals: Example

#include <signal.h>#include <setjmp.h>jmp_buf sjbuf;main(){ if (signal(SIGINT,SIG_IGN) != SIG_IGN) signal(SIGINT,onintr); setjmp(sjbuf); /* save current stack position */ /* main loop */ }onintr(){ signal(SIGINT, onintr); /* reset for next interrupt */ longjmp(sjbuf, 0); /* jump to saved state */ }

Page 13: Unix System Programming

13

Signals: Alarm

alarm(): causes SIGALRM sent to process n sec later/* “timeout prog” run prog and abort it after 3600 sec */main(){ if ((pid=fork()) == 0) execvp(argv[1], &argv[1]); signal(SIGALRM, onalarm); alarm(3600); if (wait(&status) == -1 || status & 0177) != 0) error(“%s killed”,argv[1]); }

onalarm() /* kill child when alarm arrives */{ kill(pid, SIGKILL); /* send pid the signal */ }

Page 14: Unix System Programming

14

Outline

UNIX system programming IPC with shared memory IPC with message passing

Page 15: Unix System Programming

15

Accessing Shared Data

Consider two processes, each of which is to add one to a shared data item, x

Page 16: Unix System Programming

16

Critical Section

A mechanism for ensuring that only one process accesses a particular resource at a time is to establish sections of code involving the resource as critical sections and arrange that only one such critical section is executed at a time The first process to reach a critical section for a

particular resource enters and executes the section. The process prevents all other processes from their

critical sections for the same resource. Once the process has finished its critical section,

another process is allowed to enter a critical section for the same resource.

This mechanism is known as mutual exclusion.

Page 17: Unix System Programming

17

Locks

The simplest mechanism for ensuring mutual exclusion of critical sections.

A lock is a 1-bit variable that is a 1 to indicate that a process has entered the critical section and a 0 to indicate that no process is in the critical section. The lock operates much like that of a door lock. A process coming to the “door” of a critical section

and finding it open may enter the critical section, locking the door behind it to prevent other processes from entering

Once the process has finished the critical section, it unlocks the door and leaves.

Page 18: Unix System Programming

18

Spin Lock

while (lock == 1) do_nothing; /* no operation in while loop */

lock = 1; /* enter critical section */critical section

lock = 0; /* leave critical section */

Page 19: Unix System Programming

19

Pthread Lock Routines

Locks are implemented in Pthreads with mutually exclusive lock variables, or “mutex” variables A mutex must be declared as of type

pthread_mutex_t and initialized, usually in the “main” thread:

pthread_mutex_t mutex1;..

pthread_mutex_init(&mutex1, NULL); NULL specifies a default attribute for the mutex. A mutex can be destroyed with

pthread_mutex_destroy()

Page 20: Unix System Programming

20

Pthread Lock Routines (Cont’d)

A critical section can then be protected using pthread_mutex_lock() and pthread_mutex_unlock():

pthread_mutex_lock(&mutex1);.critical section.

pthread_mutex_unlock(&mutex1); If a thread reaches a mutex lock and finds it locked,

it will wait for the lock to open. If more than one thread is waiting for the lock to

open when it opens, the system will select one thread to be allowed to proceed.

Only the thread that locks a mutex can unlock it.

Page 21: Unix System Programming

21

Semaphores

A semaphore, s, is a positive integer (including zero) operated upon by two operations named P and V. P operation, P(s): waits until s is greater than zero

and then decrements s by one and allows the process to continue.

V operation, V(s): increments s by one to release one of the waiting processes (if any).The P and V operations are performed indivisibly.A mechanism for activating waiting processes is also

implicit in the P and V operations.Though the exact algorithm is not specified, the algorithm

is expected to be fair.Processes delayed by P(s) are kept in abeyance until

released by a V(s) on the same semaphore.

Page 22: Unix System Programming

22

Semaphore for Critical Sections Use a binary semaphore, which acts as a lock variable, but P

and V operations should include process scheduling The semaphore is initialized to 1, indicating that no

process is in its critical section Each mutually exclusive critical section is preceded by a

P(s) and terminated with a V(s), i.e.,Process 1 Process 2 Process 3Noncritical section Noncritical section Noncritical section

. . .P(s) P(s) P(s)

Critical section Critical section Critical sectionV(s) V(s) V(s). . .

Noncritical section Noncritical section Noncritical section

Page 23: Unix System Programming

23

Semaphore for Critical Sections (Cont’d)

Any process might reach its P(s) operation first (or more than one process may reach it simultaneously).

The first process to reach its P(s) operation, or to be accepted, will set the semaphore to 0, inhibiting the other processes from proceeding past their P(s) operations Any process reaching its P(s) operation will be

recorded so that one can be selected when the critical section is released

When the process reaches its V(s) operation, it sets the semaphore s to 1 and one of the processes waiting is allowed to proceed into its critical section.

Page 24: Unix System Programming

24

General Semaphore

Can take on positive values other than zero and one. Such semaphores provide, for example, a means of

recording the number of “resource units” available or used and can be used to solve producer/consumer problems.

Semaphore routines exist for UNIX processes. They do not exist in Pthreads as such, though they can be written and they do exist in the real-time extension to Pthreads

Semaphores can be used to implement most critical section applications, but they are open to human errors: Every P must have a corresponding V

=> omission of a P or V, or misnaming the semaphore ...

Page 25: Unix System Programming

25

Program Examples

To sum the elements of an array, a[1000]:int sum, a[1000];sum = 0;for (i = 0; i < 1000; i++)

sum = sum + a[i];

Page 26: Unix System Programming

26

Using Unix Processes

Divide the calculation into two parts:Process 1 Process 2sum1 = 0; sum2 = 0;for (i = 0; i < 1000; i = i + 2) for (i = 1; i < 1000; i = i + 2)

sum1 = sum1 + a[i]; sum2 = sum2 + a[i]; sum = sum + sum1; sum = sum + sum2; The result location, sum, will need to be shared and

access protected by a lock Use a shared data structure:

Page 27: Unix System Programming

27

#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <stdio.h>#include <errno.h>#define array_size 1000 /* no of elements in shared

memory */extern char *shmat();void P(int *s);void V(int *s);

The Code

Page 28: Unix System Programming

28

int main(){

int shmid, s, pid; /* shared memory, semaphore, proc id */char *shm; /*shared mem. addr returned by shmat()*/int *a, *addr, *sum; /* shared data variables*/int partial_sum; /* partial sum of each process */int i;/* initialize semaphore set */int init_sem_value = 1;s = semget(IPC_PRIVATE, 1, (0600 | IPC_CREAT));if (s == -1) { /* if unsuccessful*/

perror("semget");exit(1); }

if (semctl(s, 0, SETVAL, init_sem_value) < 0) {perror("semctl");exit(1); }

Page 29: Unix System Programming

29

/* create segment*/shmid = shmget(IPC_PRIVATE,(array_size*sizeof(int)+1),

(IPC_CREAT|0600));if (shmid == -1) {

perror("shmget");exit(1); }

/* map segment to process data space */shm = shmat(shmid, NULL, 0);/* returns address as a character*/if (shm == (char*)-1) {

perror("shmat");exit(1); }

addr = (int*)shm; /* starting address */sum = addr; /* accumulating sum */addr++;a = addr; /* array of numbers, a[] */

Page 30: Unix System Programming

30

*sum = 0;for (i=0; i < array_size; i++) /* load array with numbers */

*(a + i) = i+1;pid = fork(); /* create child process */if (pid == 0) { /* child does this */

partial_sum = 0;for (i = 0; i < array_size; i = i + 2) partial_sum += *(a +

i);}else { /* parent does this */

partial_sum = 0;for (i = 1; i < array_size; i = i + 2) partial_sum += *(a + i);}

P(&s); /* for each process, add partial sum */*sum += partial_sum;

V(&s);printf("\nprocess pid=%d, partial sum=%d\n",pid,partial_sum);if (pid == 0) exit(0); else wait(0); /* terminate child proc */printf("\nThe sum of 1 to %i is %d\n", array_size, *sum);

Page 31: Unix System Programming

31

/* remove semaphore */if (semctl(s, 0, IPC_RMID, 1) == -1) {

perror("semctl"); exit(1); }/* remove shared memory */if (shmctl(shmid, IPC_RMID, NULL) == -1) {

perror("shmctl"); exit(1); }} /* end of main */

void P(int *s) /* P(s) routine*/{ struct sembuf sembuffer, *sops;

sops = &sembuffer; sops->sem_num = 0;sops->sem_op = -1; sops->sem_flg = 0;if (semop(*s, sops, 1) < 0) {

perror("semop"); exit(1); }return;

}

Page 32: Unix System Programming

32

void V(int *s) /* V(s) routine */{ struct sembuf sembuffer, *sops;

sops = &sembuffer;sops->sem_num = 0;sops->sem_op = 1;sops->sem_flg = 0;if (semop(*s, sops, 1) <0) {

perror("semop");exit(1); }

return;}

SAMPLE OUTPUTprocess pid = 0, partial sum = 250000process pid = 26127, partial sum = 250500The sum of 1 to 1000 is 500500

Page 33: Unix System Programming

33

Using Pthreads n threads are created, each taking numbers from the list

to add to their sums. When all numbers have been taken, threads add their partial results to a shared location sum.

The shared location global_index is used by each thread to select the next element of a[].

After index is read, it is incremented in preparation for the next element to be read.

Result in sum, need to be shared and protected by a lock.

Page 34: Unix System Programming

34

The Code

#include <stdio.h>#include <pthread.h>#define array_size 1000#define no_threads 10

/* shared data */int a[array_size]; /* array of numbers to sum */int global_index = 0; /* global index */int sum = 0; /* final result, also used by slaves */pthread_mutex_t mutex1; /* mutually exclusive lock

variable */

Page 35: Unix System Programming

35

void *slave(void *ignored) /* Slave threads */{ int local_index, partial_sum = 0;

do { pthread_mutex_lock(&mutex1);/* get next index */

local_index = global_index;/* read current index & save locally*/

global_index++; /* increment global index */ pthread_mutex_unlock(&mutex1); if (local_index < array_size)

partial_sum += *(a + local_index);} while (local_index < array_size);

pthread_mutex_lock(&mutex1); /* add to global sum */sum += partial_sum;

pthread_mutex_unlock(&mutex1);return (); /* Thread exits */

}

Page 36: Unix System Programming

36

main () {int i;pthread_t thread[10]; /* threads */pthread_mutex_init(&mutex1,NULL); /* initialize mutex */for (i = 0; i < array_size; i++) /* initialize a[] */

a[i] = i+1;for (i = 0; i < no_threads; i++) /* create threads */

if (pthread_create(&thread[i], NULL, slave, NULL) != 0)perror("Pthread_create fails");

for (i = 0; i < no_threads; i++) /* join threads */if (pthread_join(thread[i], NULL) != 0)

perror("Pthread_join fails");printf("The sum of 1 to %i is %d\n", array_size, sum);

} /* end of main */

Page 37: Unix System Programming

37

Outline

UNIX system programming IPC with shared memory IPC with message passing

Page 38: Unix System Programming

38

Pipes for IPC

Unidirectional byte stream communication mechanisme.g., ls | pr -2 | lpr

int sk[2]; /* sk[0]: read-end; sk[1]: write-end */pipe(sk); /* create a pipe */if (fork()) { /* the parent */ close(sk[1]); while(read(sk[0],buf,SIZE) > 0) printf("%s",buf); }else { /* the child */ close(sk[0]); fd=popen("ps -l","r"); while((s=read(fd,buf,SIZE)) > 0) write(sk[1],buf,s); }

Page 39: Unix System Programming

39

34ex2

(a)

3ex2

(b)

4ex2

fork()

3ex2

34ex2

csh

01ps

(c)

Page 40: Unix System Programming

40

Sockets

Endpoints for communication and for IPC references; treated like files

Socket type: stream (TCP), datagram (UDP), raw Socket domain:

UNIX: socket name = path name Internet: socket name = Internet addr + port #

e.g., 140.114.77.100 and 1800 struct sockaddr_in { short sin_family; /* domain name */ u_short sin_port; /* port address */ struct in_addr sin_addr; /* Internet address */ char sin_zero[8]; /* padding bytes */ };

Page 41: Unix System Programming

41

Socketpair for IPC

Two-way stream communication under UNIX domain int sk[2];

socketpair(AF_UNIX,SOCK_STREAM,0,sk);for (i=0; i<nchild; i++) if (fork() == 0) { close(sk[0]); while (read(sk[1],&num,4) > 0) { num = num*num; write(sk[1],&num,4); }exit(0); }close(sk[1]);for (i=0, pt=a; i<n; i++, pt++) write(sk[0],pt,4);for (i=0, pt=a; i<n; i++, pt++) read(sk[0],pt,4);

Page 42: Unix System Programming

42

34ex3

(a)

(b)

3ex3

4ex34ex34ex3

Page 43: Unix System Programming

43

Datagram: Internet Domain

The sender:struct sockaddr_in remote;struct hostent *hp,*gethostbyname();sk = socket(AF_INET,SOCK_DGRAM,0);remote.sin_family = AF_INET; /* wild-card NW addr */hp = gethostbyname(”cs20"); /* get NW addr of cs20 */bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp-

>h_length);remote.sin_port = port_no; /* got from receiver */sendto(sk,MSG,strlen(MSG),0,&remote,sizeof(remote));read(sk,buf,BUFSIZ);

Page 44: Unix System Programming

44

Datagram: Internet Domain (cont.)

The receiver:struct sockaddr_in local,remote;sk = socket(AF_INET,SOCK_DGRAM,0);local.sin_family = AF_INET;local.sin_addr.s_addr = INADDR_ANY;local.sin_port = 0; /* let system assign a port */bind(sk,&local,sizeof(local));getsockname(sk,&local,&len); /* get the assigned port */printf("Port number = %d",local.sin_port); /* publish it */recvfrom(sk,buf,BUFSIZ,0,&remote,&rlen);sendto(sk,MSG,strlen(MSG),0,&remote,sizeof(remote));

Page 45: Unix System Programming

45

Virtual Circuit: Internet Domain

The server:sk = socket(AF_INET,SOCK_STREAM,0);local.sin_family = AF_INET;local.sin_addr.s_addr = INADDR_ANY;local.sin_port = 0;bind(sk,&local,sizeof(local));listen(sk,5); /* will accept 5 connections */while (1) { rsk = accept(sk,0,0); if (fork() == 0) { /* fork one child for one request */ dup2(rsk,0); execlp("recho","recho",0); } else close(rsk); }

Page 46: Unix System Programming

46

Virtual Circuit: Internet Domain (cont.)

The child server: (the “recho” process)while (read(0,buf,BUFSIZ) > 0) printf("%s",buf);

The client:sk = socket(AF_INET,SOCK_STREAM,0);remote.sin_family = AF_INET;hp = gethostbyname(”cs20");bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp->h_length);remote.sin_port = port_no; /* got from receiver */connect(sk,&remote,sizeof(remote));while(read(0,buf,BUFSIZ) > 0) write(sk,buf,strlen(buf);

Page 47: Unix System Programming

47

Non-blocking Receive

Receive will not block the process if no data arrivedsk = socket(sk,AF_UNIX,SOCK_DGRAM,0);fcntl(sk,F_SETFL,FNDELAY); /* work on descriptor to set

(F_SETFL) the status flag to non-blocking */ /* Bind socket “local” */while(read(sk,buf,BUFSIZ) < 0) /* return immediately */ if(errno == EWOULDBLOCK) sleep(5); /* if no data arrived => sleep 5 seconds */printf("%s",buf);

Page 48: Unix System Programming

48

I/O Multiplexing

Listen to several events and respondsk = socket(AF_INET,SOCK_DGRAM,0); /* Bind sockets “local” and “remote” */while(1) { mask = 1 << sk | 1; /* poll stdin and sk for input */ select(20,&mask,0,0,0); /* return if any one input */ if ((mask & 1) > 0) { /* stdin has input: send */ c=read(0,buf,BUFSIZ); sendto(sk,buf,c,0,&remote,rlen); } if ((mask & (1 << sk)) > 0) /* sk has input: receive */ c=recv(sk,buf,BUFSIZ,0); }

Page 49: Unix System Programming

49

Broadcasting

Use datagram communication to broadcast to all hosts in a particular sub-network

The remote or destination host network address must be INADDR_ANY#define NET "140.114.77"sk = socket(AF_INET,SOCK_DGRAM,0); /* do binding for socket “local” */remote.sin_family = AF_INET;remote.sin_addr = inet_makeaddr( inet_network(NET),INADDR_ANY);remote.sin_port = portn;


Recommended