640 likes | 657 Views
Learn about interprocess communication using pipes in C programming, how to create, manage, and utilize them efficiently.
E N D
1. Pipes • A form of interprocess communication Between processes that have a common ancestor • Typical use: • Pipe created by a process • Process calls fork() • Pipe used between parent and child
Differences between versions • All systems support half-duplex • Data flows in only one direction • Many newer systems support full duplex • Data flows in two directions • For portability, assume only half-duplex
Creating a pipe #include <unistd.h> int pipe(int filedes[2]); • Returns 0 if ok, -1 on error • Returns two file descriptors • filedes[0] is open for reading • filedes[1] is open for writing • Output of filedes[1] is input to filedes[0]
After the pipe() call Filedes 0 1 3 4
The process then calls fork() Child Parent
And then …. • We close the read end in one process • And close the write end in the other process • To get ….
Parent writing to child Child Parent
Child writing to parent Child Parent
After one end of the pipe is closed … • Reading from a empty pipe whose write end has been closed returns 0 (indicating EOF) • Writing to a pipe whose read end has been closed generates a SIGPIPE signal • If we ignore the signal or catch and return, handler returns -1, and errno set to EPIPE
Example … #include <unistd.h> #include <stdio.h> int main(void){ int n; // to keep track of num bytes read int fd[2]; // to hold fds of both ends of pipe pid_t pid; // pid of child process char line[80]; // buffer to hold text read/written …
Continued … if (pipe(fd) < 0) // create the pipe perror("pipe error"); if ((pid = fork()) < 0) { // fork off a child perror("fork error"); } else if (pid > 0) { // parent process close(fd[0]); // close read end write(fd[1], "hello world\n", 12); // write to it }…
continued } else { // child process close(fd[1]); // close write end n = read(fd[0], line, 80); // read from pipe write(1, line, n); // echo to screen } exit(0); }
dup() and dup2 #include <unistd.h> int dup(int filedes); int dup2(int filedes, int filedes2); • Both will duplicate an existing file descriptor • dup() returns lowest available file descriptor, now referring to whatever filedes refers to • dup2() - filedes2 (if open) will be closed and then set to refer to whatever filedes refers to
DUP • Duplicate a file descriptor (system call) int dup( int fd ); duplicates fd as the lowest unallocated descriptor • • Commonly used to redirect stdin/stdout • • Example: redirect stdin to “foo” int fd; fd = open(“foo”, O_RDONLY, 0); close(0); dup(fd); close(fd);
DUP2 • For convenience… dup2( int fd1, int fd2 ); • use fd2(new) to duplicate fd1 (old) • closes fd2 if it was in use • • Example: redirect stdin to “foo” fd = open(“foo”, O_RDONLY, 0); dup2(fd,0); close(fd);
Pipes and Standard I/O int pid, p[2]; if (pipe(p) == -1) exit(1); pid = fork(); if (pid == 0) { close(p[1]); dup2(p[0],0); close(p[0]); ... read from stdin ... } else { close(p[0]); dup2(p[1],1); close(p[1]); ... write to stdout ... wait(&status); }
Pipes and Exec() int pid, p[2]; if (pipe(p) == -1) exit(1); pid = fork(); if (pid == 0) { close(p[1]); dup2(p[0],0); close(p[0]); execl(...); } else { close(p[0]); dup2(p[1],1); close(p[1]); ... write to stdout ... wait(&status); }
‘ls | more’ example When command shells interprets ‘ls | more’, it: 1. Invokes the pipe( ) system call; let us assume that pipe( ) returns the filedescriptors 3 (the pipe's read channel ) and 4 (the write channel ). 2. Invokes the fork( ) system call twice. 3. Invokes the close( ) system call twice to release file descriptors 3 and 4.
‘ls | more’ example The first child process, which must execute the ls program, performs the following operations: 1. Invokes dup2(4,1) to copy file descriptor 4 to file descriptor 1. From now on, filedescriptor 1 refers to the pipe's write channel. 2. Invokes the close( ) system call twice to release file descriptors 3 and 4. 3. Invokes the execve( ) system call to execute the /bin/ls program. By default, such a program writes its output to the file having filedescriptor 1 (the standard output), that is, it writes into the pipe.
‘ls | more’ example The second child process must execute the more program; therefore, it performs the followingoperations: 1. Invokes dup2(3,0) to copy file descriptor 3 to file descriptor 0. From now on, filedescriptor 0 refers to the pipe's read channel. 2. Invokes the close( ) system call twice to release file descriptors 3 and 4. 3. Invokes the execve( ) system call to execute /bin/more. By default, that programreads its input from the file having file descriptor (the standard input); that is, it readsfrom the pipe.
popen and pclose #include <stdio.h> FILE *popen(const char *cmdstring, const char *type); • The popen( ) functionreceives two parameters: • the cmdstringpathname of an executable file • a typestringspecifying the direction of the data transfer (r or w). • It returns the pointer to a FILEdata structure (fp). • popen runs cmdstring with output or input directed to fp based on value of typeparameter. • Handle the “dirty work” of creating pipe, forking child, closing unused ends, executing shell to run program, waiting for command to terminate int pclose(FILE *fp); • The pclose( ) function, which receives the file pointer returned by popen( ) as itsparameter, simply invokes the wait4( ) system call and waits for the termination of theprocess created by popen( ).
Other techniques for IPC • Socket programming • We have seen this before in internet engineering. • It is mainly used for IPC between two network processes. • Semaphores • Seen before. • Shared memory • shmget()forCreate/Access Shared Memory • shmat()forAccessing Shared Memory • shmctl()for controlling shared memory • shmdt()for deleting shared memory • Messages • msgget( KEY, IPC_CREAT|IPC_EXCL…) for Create/access: • msgctl( id, IPC_RMID ) for Control: • Send/receive • msgsnd( id, buf, text_size, flags ) • msgrcv( id, buf, max_size, flags ) • FIFO • mkfifo( )specifically to create a FIFO. • Once created, a FIFO can be accessed through the usual open( ), read( ), write( ), andclose( )system calls.
Directory Structure • A directory ‘file’ is a sequence of lines; each line holds an i-node number and a file name. • The data is stored as binary, so we cannot simply use catto view it
I-node: • The administrative information about a file is kept in a structure known as an inode. • Inodes in a file system, in general, are structured as an array known as an inode table. • An inode number, which is an index to the inode table, uniquely identifies a file in a file system.
2. Links 2.1 What is a Link? 2.2 Creating a Link 2.3 Seeing Links 2.4 Removing a Link 2.5 Symbolic Links 2.6 Implementation
2.1. What is a Link? • A link is a pointer to a file. • Useful for sharing files: • a file can be shared by giving each person their own link (pointer) to it.
2.2. Creating a Link ln existing-file new-pointer • Jenny types: ln draft /home/bob/letter / /home/bob/draftand /home/jenny/letter home bob jenny memo planning
Changes to a file affects every link:$ cat file_a This is file A. $ ln file_a file_b $ cat file_b This is file A. $ vi file_b : $ cat file_bThis is file B after the change.$ cat file_aThis is file B after the change.
2.3. Seeing Links • Compare status information: $ ls -l file_a file_b file_c file_d-rw-r--r-- 2 dkl 33 May 24 10:52 file_a-rw-r--r-- 2 dkl 33 May 24 10:52 file_b-rw-r--r-- 1 dkl 16 May 24 10:55 file_c-rw-r--r-- 1 dkl 33 May 24 10:57 file_d • Look at inode number: $ ls -i file_a file_b file_c file_d3534 file_a 3534 file_b 5800 file_c 7328 file_d
2.4. Removing a Link • Deleting a link does not remove the file. • Only when the file and every link is gone will the file be removed.
2.5. Symbolic Links • The links described so far are often called hard links • a hard link is a pointer to a file which must be on the same file system • A symbolic link is an indirect pointer to a file • it stores the pathname of the pointed-to file • it can link across file systems
Jenny types: ln -s shared /home/dkl/project / /home/jenny/sharedand /home/dkl/project home dkl jenny separate file system memo planning
Symbolic links are listed differently: $ ln -s pics /home/mh/img $ ls -lF pics /home/mh/img drw-r--r-- 1 dkl staff 981 May 24 10:55 pics lrwxrwxrxw 1 dkl staff 4 May 24 10:57/home/mh/img --> pics
new abc 2.6 Link Creation, Update & Removal cp bob new ln bob new ln -s bob new bob abc abc abc update new delete new bob new bob new new ? bob XY abc abc XY abc abc XY continued
2.7 link() and unlink() #include <unistd.h> int link( const char *oldpath, const char *newpath ); • Meaning of:link( “abc”, “xyz” ) : “fred.html” 120 “abc” 207 135 “bookmark.c” “xyz” 207 : continued
unlink() clears the directory record • usually means that the i-node number is set to 0 • The i-node is only deleted when the last link to it is removed; the data block for the file is also deleted (reclaimed) & no process have the file opened
Example: unlink #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> int main(void) { if( open( "tempfile", O_RDWR ) < 0 ) { perror( "open error“ ); exit( 1 ); } if( unlink( "tempfile“ ) < 0 ) { perror( "unlink error“ ); exit( 1 ); } printf( "file unlinked\n“ ); exit(0); }
symlink() #include <unistd.h> int symlink(const char *oldpath, const char *newpath); • Creates a symbolic link named newpath which contains the string oldpath. • Symbolic links are interpreted at run-time. • Dangling link – may point to an non-existing file. • If newpath exists it will not be overwritten.
readlink() #include <unistd.h> int readlink( const char *path, char *buf, size_t bufsiz ); • Read value of a symbolic link (does not follow the link). • Places the contents of the symbolic link path in the buffer buf, which has size bufsiz. • Does not append a NULL character to buf. • Return value • The count of characters placed in the buffer if it succeeds. • -1 if an error occurs.
3. Subdirectory Creation • “mkdir uga” causes: • the creation of a uga directory file and an i-node for it • an i-node number and name are added to the parent directory file : 120 “fred.html” 207 “abc” 135 “bookmark.c” “uga” 201 :
4. “.” and “..” • “.” and “..” are stored as ordinary file names with i-node numbers pointing to the correct directory files. • Example: dkl book memos continued
In more detail: Directory ben 123 “.” 247 “..” 260 “book” 401 “memos” Directory book Directory memos 260 “.” 401 “.” 123 “..” 123 “..” 566 “chap1” 800 “kh” 567 “chap2” 810077 “kd” 590 “chap3” 590 “mw”
5. mkdir() • #include <sys/types.h>#include <fcntl.h>#include <unistd.h>int mkdir(char *pathname, mode_t mode); • Creates a new directory with the specified mode: return 0 if ok, -1 on error continued
“.” and “..” entries are added automatically • mode must include execute permissions so the user(s) can use cd. e.g. 0755
6. rmdir() • #include <unistd.h>int rmdir(char *pathname); • Delete an empty directory;return 0 if ok, -1 on error. • Will delay until other processes have stopped using the directory.
7. Reading Directories • #include <sys/types.h>#include <dirent.h>DIR *opendir(char *pathname);struct dirent *readdir(DIR *dp);int closedir(DIR *dp); returns apointer if ok, NULLon error returns apointer if ok, NULL at end or on error
dirent and DIR • struct dirent {long d_ino; /* i-node number */char d_name[NAME_MAX+1]; /* fname */off_t d_off; /* offset to next rec */unsigned short d_reclen; /* record length */ } • DIR is a directory stream (similar to FILE) • when a directory is first opened, the stream points to the first entry in the directory