Download presentation
Presentation is loading. Please wait.
Published byReynold Howard Modified over 9 years ago
1
2.3 InterProcess Communication (IPC)
2
IPC methods ► Signals ► Mutex (MUTual EXclusion) ► Semaphores ► Shared memory ► Memory mapped files ► Pipes & named pipes ► Sockets ► Message queues ► MPI (Message Passing Interface) ► Barriers
3
IPC methods 1. thread to thread 2. process to process (both on same system) 3. system to system (i.e., processes on different systems)
4
IPC methods between threads ► Mutex ► Semaphores
5
IPC methods between processes ► Signals ► Shared memory ► Memory mapped files ► Pipes & named pipes ► Message queues
6
IPC methods between systems ► Sockets ► MPI (Message Passing Interface) Barriers
7
Signals
8
Signals ► software interrupts ► async ► can be recognized or ignored
9
Signals #include #include //defn. of signal handler function typedef void (*sighandler_t)(int); //function call to establish a signal handler sighandler_t signal ( int signum, sighandler_t handler ); What is this?
10
Remember... char* ptr1, ptr2; is not the same as char* ptr1; char* ptr2; It really means char *ptr1, ptr2; Use char *ptr1, *ptr2; instead.
11
Allowed signals (see kill –l) 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 32) SIGRTMIN 33) SIGRTMIN+1 34) SIGRTMIN+2 35) SIGRTMIN+3 36) SIGRTMIN+4 37) SIGRTMIN+5 38) SIGRTMIN+6 39) SIGRTMIN+7 40) SIGRTMIN+8 41) SIGRTMIN+9 42) SIGRTMIN+10 43) SIGRTMIN+11 44) SIGRTMIN+12 45) SIGRTMIN+13 46) SIGRTMIN+14 47) SIGRTMIN+15 48) SIGRTMAX-15 49) SIGRTMAX-14 50) SIGRTMAX-13 51) SIGRTMAX-12 52) SIGRTMAX-11 53) SIGRTMAX-10 54) SIGRTMAX-9 55) SIGRTMAX-8 56) SIGRTMAX-7 57) SIGRTMAX-6 58) SIGRTMAX-5 59) SIGRTMAX-4 60) SIGRTMAX-3 61) SIGRTMAX-2 62) SIGRTMAX-1 63) SIGRTMAX ► Also see man 7 signal for a lengthier description.
12
As reported by kill -l on SunOS/Solaris (Sun’s Unix) ► HUP, INT, QUIT, ILL, TRAP, ABRT, EMT, FPE, KILL, BUS, SEGV, SYS, PIPE, ALRM, TERM, USR1, USR2, CLD, PWR, WINCH, URG, POLL, STOP, TSTP, CONT, TTIN, TTOU, VTALRM, PROF, XCPU, XFSZ, WAITING, LWP, FREEZE, THAW, CANCEL, LOST, XRES, JVM1, JVM2, RTMIN, RTMIN+1, RTMIN+2, RTMIN+3, RTMAX-3, RTMAX-2, RTMAX-1, RTMAX
13
Sending a signal to a process ► Use the kill command (see man kill). kill [ -s signal | -p ] [ -a ] [ -- ] pid... kill -l [ signal ] ► Use the kill function (see man 2 kill) #include #include int kill ( pid_t pid, int sig );
14
Signal example code //define the signal hander function void myHandler ( int signalNo ) { …}… //define the signal handler // (typically done once in main) signal( SIGCHLD, myHandler );
15
Mutex Used to control access to shared memory and other resources, in general.
16
Race condition ► An error where one process may wait forever or other inconsistencies may result ► Occurs when two or more processes are reading or writing some shared data ► Applies to threads as well ► The final result depends on process or thread runs, precisely when they run, and in what order they run. ► Difficult to debug and reproduce errors.
17
Critical region/section ► Part of program where shared memory is accessed Must be identified ► mutual exclusion (mutex) method to exclude other processes from using a shared variable until our process is finished with it
18
Process cooperation rules: 1. No two processes can be in their critical sections at the same time. 2. Make no timing assumptions. ► My code is faster/shorter; my processor is faster. ► My priority is higher. ► The probability is small for us both processes to do this at the same time. 3. (progress) A process should not be blocked from entering a critical region if all other processes are outside the critical region. 4. (bounded wait) No process should have to wait forever to get into its critical region.
19
Mutual exclusion w/ busy waiting Methods to implement mutex: 1.Disable interrupts 2.Lock variables 3.Strict alternation 4.Peterson’s solution 5.TSL instruction
20
Mutex method 1: disable interrupts ► OK for (and used by) OS Consideration for MP systems ► NOT OK for apps Why not?
21
Mutex method 2: lock vars ► software method ► employs single, shared lock variable initially = 0 ► uses busy wait spin lock
22
Mutex method 2: lock vars shared int x=0; //wait for lock while (x!=0) ; // note the empty statement x=1; //get lock //critical section … //end critical section x=0; //release lock ► Doesn’t work (w/out hardware support). ► What about performance?
23
Mutex method 3: strict alternation
24
► Software ► Problem: violates process cooperation rule #3. Because in strict alternation, a process can be blocked from entering its C.S. by a process NOT in its C.S. ► In general, a process can’t be in it’s C.S. 2x in a row. ► The 2 processes must be running at about the same speed.
25
Mutex method 4: Peterson’s (sofware) soln.
26
Mutex method 4: Peterson’s (software) soln.
27
Mutex method 4: Peterson’s soln. (software)
28
Mutex method 4: Peterson’s (sofware) soln. ► Works, but suffers from busy wait. ► Has been generalized to more than 2 processes (but the above is only for 2).
29
Mutex method 5: TSL instruction ► TSL = Test and Set Locked ► TSL RX, LOCK RX = register; LOCK = memory location Step 1: read contents of LOCK into RX Step 2: sets LOCK to 1 Indivisible instruction (non interruptible) Memory, not cache Locks memory bus (so other processors can’t access/change LOCK) ► IA32 xchg and lock instructions
30
Mutex method 5: TSL instruction
31
Priority inversion problem ► an unexpected consequence of busy wait ► given H (a high priority job), and L (low priority job) ► scheduling algorithm: whenever H is ready to run, L is preempted and H is run.
32
Priority inversion problem H runs… H blocks on I/O I/O completes H runs … H attempts to enter C.S. H busy waits forever! L is ready to run L runs … L enters C.S. … … L is preempted......
33
Using mutex (provided by OS) ► Simpler than semaphore ► Two states: locked or unlocked ► Functions: Declare mutex variable Initialize mutex variable (just once) lock ---> C.S. ---> unlock
34
#include #include … pthread_mutex_t mutex; ///< declare global (i.e., not inside of any function) … //perform this one-time initialization (usually in main) int ret = pthread_mutex_init( &::mutex, NULL ); if (ret) { perror( "main: mutex init error" ); exit(-1); } … //lock in thread code ret = pthread_mutex_lock( &::mutex ); if (ret) { printf( "%d: mutex lock error \n", tp->whoAmI ); } //critical section here //critical section here //unlock in thread code pthread_mutex_unlock( &::mutex );
35
#include #include … CRITICAL_SECTION g_cs; … //perform this one-time initialization (usually in main) InitializeCriticalSection( &g_cs ); … //lock in thread code EnterCriticalSection( &g_cs ); //critical section here //critical section here //unlock in thread code LeaveCriticalSection( &g_cs );
36
Problem: ► Modify filter program to also determine overall min and max of input data. 1. Can you do this with global variables? 2. Can you do this without global variables? ► Which method requires mutex?
37
Semaphores
38
(Bounded) Producer-Consumer ► A producer produces some item and stores it in a warehouse. ► A consumer consumes an item by removing an item from the warehouse. ► Notes: The producer must pause production if the warehouse fills up (bounded). If the warehouse is empty, the consumer must wait for something to be produced.
39
(Bounded) producer- consumer problem Danger, Will Robinson (a shared variable)!
40
(Bounded) Producer-consumer problem ► Buffer is initially empty. ► Consumer checks count. It’s 0. ► Scheduler interrupts consumer (puts consumer on ready queue). ► Producer runs. Insert data into buffer. Count is 1 so producer wakes up consumer. But consumer is not asleep just yet! (The scheduler interrupted it right before the call to sleep().) Producer keeps inserting data into buffer until it’s full. Then producer goes to sleep! ► Scheduler runs consumer. Consumer thinks count=0 so it goes to sleep! ► Both sleep forever!
41
Semaphores ► Invented by Dutch computer scientist Edsger Dijkstra. ► Two basic operations: 1.Up ► increments the value of the semaphore ► historically denoted as V (also known as signal) 2.Down ► decrements the value of the semaphore ► P (also known as wait)
42
Semaphores Types: 1.POSIX ► Shared only among threads. 2.Windows ► system-wide. ► Can be system-wide. 3.System V ► Can be shared according to user-group-other (can be system-wide).
43
Binary semaphores = mutex ► Create semaphore and initialize it to 1. 1 = unlocked 0 = locked ► Then to use this as a mutex: down ► c.s. up
44
POSIX SEMAPHORES
45
POSIX Semaphores (shared among threads only) #include #include 1. int sem_init ( sem_t* sem, int pshared, unsigned int value ); 2. int sem_wait ( sem_t* sem ); 3. int sem_trywait ( sem_t* sem ); 4. int sem_post ( sem_t* sem ); 5. int sem_getvalue ( sem_t* sem, int* sval ); 6. int sem_destroy ( sem_t* sem );
46
POSIX Semaphores int sem_init ( sem_t* sem, int pshared, unsigned int value ); initialize pshared must be 0 on (some versions of) Linux ► semaphore is not shared by processes Value is initial value for semaphore.
47
POSIX Semaphores int sem_wait ( sem_t* sem ); down (if possible/blocking) int sem_trywait ( sem_t* sem ); nonblocking down ► Blocking?
48
POSIX Semaphores int sem_post ( sem_t* sem ); up (nonblocking) int sem_getvalue ( sem_t* sem, int* sval ); get the current semaphore value int sem_destroy ( sem_t* sem ); finish using the semaphore
49
WINDOWS SEMAPHORES
50
Windows Semaphores HANDLE WINAPI CreateSemaphore ( __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, __in LONG lInitialCount, __in LONG lInitialCount, __in LONG lMaximumCount, __in LONG lMaximumCount, __in_opt LPCTSTR lpName __in_opt LPCTSTR lpName); DWORD WINAPI WaitForSingleObject ( __in HANDLE hHandle, __in HANDLE hHandle, __in DWORD dwMilliseconds __in DWORD dwMilliseconds ); //decrements count by 1 BOOL WINAPI ReleaseSemaphore ( __in HANDLE hSemaphore, __in LONG lReleaseCount, __out_opt LPLONG lpPreviousCount ); //increments count by lReleaseCount BOOL WINAPI CloseHandle ( __in HANDLE hObject );
51
SYSTEM V SEMAPHORES
52
System V Semaphores (system-wide) #include #include 1. int semget ( key_t key, int nsems, int semflg ); create/access existing 2. int semctl ( int semid, int semnum, int cmd,... ); delete from system 3. int semop ( int semid, struct sembuf* sops, unsigned nsops ); used for up and down
53
Create/access existing //using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) { perror( "semget " ); perror( "semget " ); exit( -1 ); exit( -1 );} printf( "sem id=%d \n", sid ); create if necessary system-wide permissions (In C/C++, octal values start with 0.) system-wide unique number
54
Create/access existing //using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); alternative (#include ): const int sid = semget( mySemKey, 1, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); create if necessary system-wide permissions (In C/C++, octal values start with 0.)
55
Access and delete //using the key, get the semaphore id const int sid = semget( mySemKey, 1, 0700 ); if (sid==-1) { perror( "semget " ); perror( "semget " ); exit( -1 ); exit( -1 );} printf( "sem id=%d \n", sid ); //delete the semaphore semctl( sid, 0, IPC_RMID, 0 );
56
Down function static void down ( const int whichSid ) { struct sembuf sem_lock; struct sembuf sem_lock; sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_flg = 0; //operation flags sem_lock.sem_flg = 0; //operation flags if (semop(whichSid, &sem_lock, 1) == -1) { if (semop(whichSid, &sem_lock, 1) == -1) { perror("semop "); perror("semop "); exit(-1); exit(-1); }}
57
Up function static void up ( const int whichSid ) { struct sembuf sem_unlock; struct sembuf sem_unlock; sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_flg = 0; //operation flags sem_unlock.sem_flg = 0; //operation flags if (semop(whichSid, &sem_unlock, 1) == -1) { if (semop(whichSid, &sem_unlock, 1) == -1) { perror("semop"); perror("semop"); exit(-1); exit(-1); }}
58
Solution to (bounded) producer- consumer problem using semaphores (via up() and down()). Note: 3 semaphores (one used as mutex)!
59
(BOUNDED) PRODUCER- CONSUMER DEMO bounded.h,boundedProducer.cpp,boundedConsumer.cpp
60
UNBOUNDED PRODUCER- CONSUMER
61
(Unbounded) producer-consumer ► Every time the producer process runs, it produces one item. ► Every time the consumer runs, it consumes one item (or waits until one is available, and then consumes it).
62
//unbounded producer int main ( int argc, char* argv[] ) { //using the key, get the semaphore id //using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) { if (sid==-1) { perror( "semget " ); perror( "semget " ); exit( -1 ); exit( -1 ); } printf( "sem id=%d \n", sid ); printf( "sem id=%d \n", sid ); puts( "producing" ); puts( "producing" ); struct sembuf sem_unlock; struct sembuf sem_unlock; sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_flg = 0; //operation flags sem_unlock.sem_flg = 0; //operation flags if (semop(sid, &sem_unlock, 1) == -1) { if (semop(sid, &sem_unlock, 1) == -1) { perror("semop "); perror("semop "); exit(-1); exit(-1); } puts( "produced" ); puts( "produced" ); return 0; return 0;} Unbounded producer basically does an up() to indicate production.
63
//consumer int main ( int argc, char* argv[] ) { //using the key, get the semaphore id //using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) { if (sid==-1) { perror( "semget " ); perror( "semget " ); exit( -1 ); exit( -1 ); } printf( "sem id=%d \n", sid ); printf( "sem id=%d \n", sid ); puts( "consuming" ); puts( "consuming" ); struct sembuf sem_lock; struct sembuf sem_lock; sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_op = -1; //semaphore operation sem_lock.sem_flg = 0; //operation flags sem_lock.sem_flg = 0; //operation flags if (semop(sid, &sem_lock, 1) == -1) { if (semop(sid, &sem_lock, 1) == -1) { perror("semop "); perror("semop "); exit(-1); exit(-1); } puts( "consumed" ); puts( "consumed" ); return 0; return 0;} Consumer basically does a down() to indicate consumption.
64
(UNBOUNDED) PRODUCER- CONSUMER DEMO mySemKey.h, producer.cpp, consumerWait.cpp, consumerNoWait.cpp, bigProducer.cpp, delete.cpp
65
Shared Memory
66
Shared memory ► Shared memory operations shmget ► allocates a shared memory segment shmctl ► allows the user to receive information on a shared memory segment, set the owner, group, and permissions of a shared memory segment, or destroy a segment
67
Shared memory ► Shared memory operations shmat ► attaches the shared memory segment (identified by shmid) to the address space of the calling process shmdt ► detaches the shared memory segment (located at the address specified by shmaddr) from the address space of the calling process
68
Shared memory ► From the Linux sem_init man page: The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes. 1. If pshared has the value 0, then the semaphore is shared between the threads of a process, and should be located at some address that is visible to all threads (e.g., a global variable, or a variable allocated dynamically on the heap). 2. If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory.
69
Memory mapped files
70
“There comes a time when you want to read and write to and from files so that the information is shared between processes. Think of it this way: two processes both open the same file and both read and write from it, thus sharing the information. The problem is, sometimes it's a pain to do all those fseek()s and stuff to get around. Wouldn't it be easier if you could just map a section of the file to memory, and get a pointer to it? Then you could simply use pointer arithmetic to get (and set) data in the file. Well, this is exactly what a memory mapped file is. And it's really easy to use, too. A few simple calls, mixed with a few simple rules, and you're mapping like a mad-person.” http://beej.us/guide/ipc/mmap.html
71
Memory mapped files ► mmap void* mmap ( void* start, size_t length, int prot, int flags, int fd, off_t offset ); map length bytes starting at offset offset from the file specified by the file descriptor fd into memory, preferably at address start
72
Memory mapped files ► munmap int munmap ( void* start, size_t length ); The munmap system call deletes the mappings for the specified address range, and causes further references to addresses within the range to generate invalid memory references. The region is also automatically unmapped when the process is terminated. On the other hand, closing the file descriptor does not unmap the region.
73
Pipes and named pipes
74
Pipes
75
More Pipes
76
Too many pipes!
77
// Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include #include int main ( int argc, char* argv[] ) { int fd[2], nbytes; int fd[2], nbytes; pid_t childpid; pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80]; char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd ); pipe( fd ); if ((childpid = fork()) == -1) { if ((childpid = fork()) == -1) { perror( "fork" ); perror( "fork" ); exit( 1 ); exit( 1 ); } if (childpid == 0) { //Child process closes up input side of pipe if (childpid == 0) { //Child process closes up input side of pipe close( fd[0] ); close( fd[0] ); /* Send "string" through the output side of pipe */ /* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) ); write( fd[1], string, (strlen(string)+1) ); } else { //Parent process closes up output side of pipe } else { //Parent process closes up output side of pipe close( fd[1] ); close( fd[1] ); /* Read in a string from the pipe */ /* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer ); printf( "parent: received string: %s", readbuffer ); } return 0; return 0;} Pipes via pipe()
78
// Excerpt from "Linux Programmer's Guide - Chapter 6." // (C)opyright 1994-1995, Scott Burkett #include #include #define MAXSTRS 5 int main ( int argc, char* argv[] ) { FILE *pipe_fp; FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; /* Create one way pipe line with call to popen() */ /* Create one way pipe line with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { if (( pipe_fp = popen("sort", "w")) == NULL) { perror("popen"); perror("popen"); exit(1); exit(1); } /* Processing loop */ /* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) { for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], pipe_fp); fputs(strings[cntr], pipe_fp); fputc('\n', pipe_fp); fputc('\n', pipe_fp); } /* Close the pipe */ /* Close the pipe */ pclose(pipe_fp); pclose(pipe_fp); return 0; return 0;} Pipes via popen() Any valid shell command. Can be “w” or “r”.
79
// Excerpt from "Linux Programmer's Guide - Chapter 6" // (C)opyright 1994-1995, Scott Burkett #include #include #define MAXSTRS 5 int main ( int argc, char* argv[] ) { FILE *pipe_fp; FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; /* Create one way pipe line with call to popen() */ /* Create one way pipe line with call to popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { if (( pipe_fp = popen("sort", "w")) == NULL) { perror("popen"); perror("popen"); exit(1); exit(1); } /* Processing loop */ /* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) { for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], pipe_fp); fputs(strings[cntr], pipe_fp); fputc('\n', pipe_fp); fputc('\n', pipe_fp); } /* Close the pipe */ /* Close the pipe */ pclose(pipe_fp); pclose(pipe_fp); return 0; return 0;} Pipes via popen() Any valid shell command. Can be “w” or “r”. How would I modify this to have obtain the sorted information?
80
// Excerpt from "Linux Programmer's Guide - Chapter 6" // (C)opyright 1994-1995, Scott Burkett #include #include #define MAXSTRS 5 int main ( int argc, char* argv[] ) { FILE *pipe_fp; FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta"}; /* Create one way pipe line with call to popen() */ /* Create one way pipe line with call to popen() */ if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) { if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) { perror("popen"); perror("popen"); exit(1); exit(1); } /* Processing loop */ /* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) { for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], pipe_fp); fputs(strings[cntr], pipe_fp); fputc('\n', pipe_fp); fputc('\n', pipe_fp); } /* Close the pipe */ /* Close the pipe */ pclose(pipe_fp); pclose(pipe_fp); return 0; return 0;} Pipes via popen() Any valid shell command. Can be “w” or “r”. How would I modify this to have obtain the sorted information? Better but is junk.dat unique?
81
Named pipes ► Named pipes Use mkfifo command. (What is a FIFO?) Example ► mkfifo mypipe ► ls –l mypipe p rw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe ► ls –l > mypipe Hangs! Why? Ctrl-c ► ls –l > mypipe & ► cat < mypipe Doesn’t hang! Why?
82
Named pipes ► Named pipes Use mkfifo command. (What is a FIFO?) Example ► mkfifo mypipe ► ls –l mypipe p rw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe ► ls –l > mypipe Hangs! Why? Because it waits for the reader. Ctrl-c ► ls –l > mypipe & ► cat < mypipe Doesn’t hang! Why? Because the reader executes. Output on next slide.
83
Output from named pipe example ► ls –l > mypipe & ► cat < mypipe total 106412 -rwx------ 1 ggrevera ggrevera 14215 Oct 5 20:45 a.out drwx------ 5 ggrevera ggrevera 4096 Feb 3 2006 csc4025 drwx------ 4 ggrevera ggrevera 4096 Oct 3 09:59 csc4035 -rw------- 1 ggrevera ggrevera 194560 Sep 6 12:52 csc4035.tar -rw------- 1 ggrevera ggrevera 891 Dec 4 2005 dir.cpp... -rw------- 1 ggrevera ggrevera 283 Oct 5 20:44 sig.cpp [1]+ Done ls -l >mypipe Why did this finish? Because the reader read everything.
84
Sockets
85
Sockets
86
Sockets – client-side Steps: 1.socket() creates an endpoint for communication and returns a descriptor 2.connect() attempts to make a connection to another socket 3.call read() and/or write() similar to an ordinary file
87
#include #include static void error ( char* msg ) { perror( msg ); perror( msg ); exit( 0 ); exit( 0 );} int main ( int argc, char* argv[] ) { if (argc < 3) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 ); exit( 0 ); } int portno = atoi( argv[2] ); int portno = atoi( argv[2] ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket“ ); if (sockfd < 0) error( "ERROR opening socket“ );... Sockets – client-side (writes a message and reads a response)
88
Sockets – client-side... struct hostent* server = gethostbyname( argv[1] ); //does host exist? struct hostent* server = gethostbyname( argv[1] ); //does host exist? if (server == NULL) { if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); fprintf( stderr, "ERROR, no such host \n" ); exit( 0 ); exit( 0 ); } struct sockaddr_in serv_addr; struct sockaddr_in serv_addr; bzero( &serv_addr, sizeof(serv_addr) ); //move 0’s to buffer bzero( &serv_addr, sizeof(serv_addr) ); //move 0’s to buffer serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET; //copy binary data from buffer to buffer //copy binary data from buffer to buffer bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); serv_addr.sin_port = htons( portno ); //host byte order to network b.o. serv_addr.sin_port = htons( portno ); //host byte order to network b.o. if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) error( "ERROR connecting“ ); error( "ERROR connecting“ );...
89
Sockets – client-side... printf("Please enter the message: "); printf("Please enter the message: "); char buffer[256]; char buffer[256]; bzero( buffer, sizeof(buffer) ); bzero( buffer, sizeof(buffer) ); fgets( buffer, sizeof(buffer)-1, stdin ); fgets( buffer, sizeof(buffer)-1, stdin ); int n = write( sockfd, buffer, strlen(buffer) ); int n = write( sockfd, buffer, strlen(buffer) ); if (n < 0) if (n < 0) error("ERROR writing to socket"); error("ERROR writing to socket"); bzero( buffer, sizeof(buffer) ); bzero( buffer, sizeof(buffer) ); n = read( sockfd, buffer, sizeof(buffer)-1 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error("ERROR reading from socket"); if (n < 0) error("ERROR reading from socket"); printf( "%s \n", buffer ); printf( "%s \n", buffer ); return 0; return 0;}
90
Sockets – client-side (complete code) #include #include static void error ( char* msg ) { perror( msg ); perror( msg ); exit( 0 ); exit( 0 );} int main ( int argc, char* argv[] ) { if (argc < 3) { if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] ); fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 ); exit( 0 ); } int portno = atoi( argv[2] ); int portno = atoi( argv[2] ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error("ERROR opening socket"); if (sockfd < 0) error("ERROR opening socket"); struct hostent* server = gethostbyname(argv[1]); struct hostent* server = gethostbyname(argv[1]); if (server == NULL) { if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" ); fprintf( stderr, "ERROR, no such host \n" ); exit( 0 ); exit( 0 ); } struct sockaddr_in serv_addr; struct sockaddr_in serv_addr; bzero( &serv_addr, sizeof(serv_addr) ); bzero( &serv_addr, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET; bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); serv_addr.sin_port = htons( portno ); serv_addr.sin_port = htons( portno ); if (connect(sockfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) if (connect(sockfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting"); error("ERROR connecting"); printf("Please enter the message: "); printf("Please enter the message: "); char buffer[256]; char buffer[256]; bzero( buffer, sizeof(buffer) ); bzero( buffer, sizeof(buffer) ); fgets( buffer, sizeof(buffer)-1, stdin ); fgets( buffer, sizeof(buffer)-1, stdin ); int n = write(sockfd,buffer,strlen(buffer)); int n = write(sockfd,buffer,strlen(buffer)); if (n < 0) if (n < 0) error("ERROR writing to socket"); error("ERROR writing to socket"); bzero( buffer, sizeof(buffer) ); bzero( buffer, sizeof(buffer) ); n = read( sockfd, buffer, sizeof(buffer)-1 ); n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error("ERROR reading from socket"); if (n < 0) error("ERROR reading from socket"); printf( "%s \n", buffer ); printf( "%s \n", buffer ); return 0; return 0;}
91
Sockets – server-side
92
Steps: 1.socket() creates an endpoint for communication and returns a descriptor 2.bind() this is called "assigning a name to a socket“ when a socket is created with socket, it exists in a name space (address family) but has no name assigned 3.listen() To accept connections, a socket is first created with socket(), a willingness to accept incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are accepted with accept(). 4.Repeat forever: 1. accept() 2. fork() a child process that performs reads and/or writes as per ordinary file.
93
int accept ( int s, struct sockaddr* addr, socklen_t* addrlen ); ► It extracts the first connection request on the queue of pending connections, creates a new connected socket with mostly the same properties as s, and allocates a new file descriptor for the socket, which is returned. ► The newly created socket is no longer in the listening state. The original socket s is unaffected by this call.
94
/** * \file server2.cpp * \file server2.cpp * \author george j. grevera * \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on * \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott). * polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket * To compile: g++ -o server2.exe server2.cpp -lsocket */ */ #include #include static const int Port = 8090; static const bool Verbose = true; //---------------------------------------------------------------------- int main ( int argc, char* argv[] ) { //create an endpoint for communication //create an endpoint for communication if (Verbose) puts( "socket()" ); if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 ); assert( sockfd != -1 );… Sockets – server-side
95
… //assign a name to the socket //assign a name to the socket struct sockaddr_in serv_addr; struct sockaddr_in serv_addr; memset( &serv_addr, 0, sizeof(serv_addr) ); memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons( Port ); serv_addr.sin_port = htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 ); assert( ret != -1 );… Sockets – server-side
96
… //a willingness to accept incoming connections and a queue //a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen // limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); ret = listen( sockfd, 5 ); assert( ret != -1 ); assert( ret != -1 );… Sockets – server-side
97
… for ( ; ; ) { for ( ; ; ) { //extract the first connection request on the queue of pending connections, create a new connected socket with //extract the first connection request on the queue of pending connections, create a new connected socket with // mostly the same properties as s, and allocate a new file descriptor for the socket, which is returned // mostly the same properties as s, and allocate a new file descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" ); if (Verbose) puts( "parent: accept()" ); struct sockaddr_in cli_addr; struct sockaddr_in cli_addr; socklen_t clilen = sizeof( cli_addr ); socklen_t clilen = sizeof( cli_addr ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); if (Verbose) puts( "parent: fork()" ); if (Verbose) puts( "parent: fork()" ); int pid = fork(); int pid = fork(); if (pid==0) { if (pid==0) { if (Verbose) puts( "child: after fork()" ); if (Verbose) puts( "child: after fork()" ); close( sockfd ); close( sockfd ); char buffer[ 256 ]; char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) ); memset( buffer, 0, sizeof(buffer) ); puts( "child: read()" ); puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); assert( n != -1 ); printf( "child: Here is the message: %s\n", buffer ); printf( "child: Here is the message: %s\n", buffer ); puts( "child: write()" ); puts( "child: write()" ); n = write( newsockfd, "I got your message", strlen("I got your message") ); n = write( newsockfd, "I got your message", strlen("I got your message") ); assert( n != -1 ); assert( n != -1 ); close( newsockfd ); close( newsockfd ); exit( 0 ); exit( 0 ); } close( newsockfd ); close( newsockfd ); } return 0; return 0;} Sockets – server-side
98
Sockets – server-side (complete code) /** * \file server2.cpp * \file server2.cpp * \author george j. grevera * \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on * \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott). * polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket * To compile: g++ -o server2.exe server2.cpp -lsocket */ */ #include #include static const int Port = 8090; static const bool Verbose = true; //---------------------------------------------------------------------- int main ( int argc, char* argv[] ) { //create an endpoint for communication //create an endpoint for communication if (Verbose) puts( "socket()" ); if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 ); assert( sockfd != -1 ); //assign a name to the socket //assign a name to the socket struct sockaddr_in serv_addr; struct sockaddr_in serv_addr; memset( &serv_addr, 0, sizeof(serv_addr) ); memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons( Port ); serv_addr.sin_port = htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port ); if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 ); assert( ret != -1 ); //a willingness to accept incoming connections and a queue //a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen // limit for incoming connections are specified with listen if (Verbose) puts( "listen()" ); if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 ); ret = listen( sockfd, 5 ); assert( ret != -1 ); assert( ret != -1 ); for ( ; ; ) { for ( ; ; ) { //extract the first connection request on the queue of //extract the first connection request on the queue of // pending connections, create a new connected socket with // pending connections, create a new connected socket with // mostly the same properties as s, and allocate a new file // mostly the same properties as s, and allocate a new file // descriptor for the socket, which is returned // descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" ); if (Verbose) puts( "parent: accept()" ); struct sockaddr_in cli_addr; struct sockaddr_in cli_addr; socklen_t clilen = sizeof( cli_addr ); socklen_t clilen = sizeof( cli_addr ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 ); assert( newsockfd != -1 ); if (Verbose) puts( "parent: fork()" ); if (Verbose) puts( "parent: fork()" ); int pid = fork(); int pid = fork(); if (pid==0) { if (pid==0) { if (Verbose) puts( "child: after fork()" ); if (Verbose) puts( "child: after fork()" ); close( sockfd ); close( sockfd ); char buffer[ 256 ]; char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) ); memset( buffer, 0, sizeof(buffer) ); puts( "child: read()" ); puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 ); assert( n != -1 ); printf( "child: Here is the message: %s\n", buffer ); printf( "child: Here is the message: %s\n", buffer ); puts( "child: write()" ); puts( "child: write()" ); n = write( newsockfd, "I got your message", n = write( newsockfd, "I got your message", strlen("I got your message") ); strlen("I got your message") ); assert( n != -1 ); assert( n != -1 ); close( newsockfd ); close( newsockfd ); exit( 0 ); exit( 0 ); } close( newsockfd ); close( newsockfd ); } return 0; return 0;}//----------------------------------------------------------------------
99
Message queues
100
#include #include ► MSGMAX defines the max length of a message (~8K). ► Define your message(s). You may define many different messages of different lengths. struct myMessage { long mtype;//message type …//body of message (you decide) };
101
Message queues ► msgget - begin accessing (and create if necessary) a message queue int msgget ( key_t key, int msgflg ); ► msgsnd - send (enqueue) a message int msgsnd ( int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg ); ► msgrcv - receive (dequeue) a message ssize_t msgrcv ( int msqid, struct msgbuf* msgp, size_t msgsz, long msgtyp, int msgflg ); ► msgctl - misc. message queue control
102
Other IPC mechanisms: ► Monitors A collection of procedures, variables, and data structures that are all grouped together in a special kind of module or package. Only one process can be active in a monitor at any instant.
103
Monitors and the (bounded) producer- consumer problem
104
Other IPC mechanisms: ► Monitors ► Message passing (MPI) ► Barriers
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.