Download presentation
Presentation is loading. Please wait.
1
Inter Process Communication (IPC)
2.同台機器(host)上行程間的通訊. 3.在不同機器間的行程通訊用Socket程式設計
2
Pipe Pipe is a half-duplex communication channel between processes that have parent-child relation. Pipe() opens a pipe for reading at one end, and writing at the other. After creating a pipe a process usually creates another copy by fork, so that they share the pipe. Usually the parent and the child will decide whether to read from or write to the pipe, and will close the other end that they do not need.
3
The 5 basic Syscalls for I/O
int open(char *path, int flags [ , int mode ] ); (check man –s 2 open) int close(int fd); int read(int fd, char *buf, int size); int write(int fd, char *buf, int size); off_t lseek(int fd, off_t offset, int whence); fd: file descriptor, a ressource handler for a file, represented as an int Not always same use for int … sometimes file descriptor. After int go into kernel mode, kernel can inspect ax and branch to appropriate function/service Good luck for hacking linux. Look linux/kernel/, include/syscall.h
4
How it works ? a fd is an index in an OS table kernel 0xFFFF stack …
mozilla foo.exe 0xFFFF stack … forbidden File descriptor tables process can not forge fds heap Kernel maintain in its own space the fd table here map an entry to a place on the disk. So process can’t read anything on the disk. Restricted again by what OS propose. sys_close(){…} fd = open(“/tmp/foo.txt“); sys_open(){…} push 0x010F mov ax,3 int 0x80 mov bx, ax will check if foo.exe can access foo.txt interrupt table 0x0000 code
5
Standard Input, Output and Error
Now, every process in Unix starts out with three file descriptors predefined: File descriptor 0 is standard input. File descriptor 1 is standard output. File descriptor 2 is standard error. You can read from standard input, using read(0, ...), and write to standard output using write(1, ...) or using two library calls printf Scanf So int fd = open(“/tmp/foo.txt”,O_RDONLY); should return 3 Can also explain redirection with the shell ? Or ask question ? Use ls /proc/self/fd to see the devices/files they point to
6
Low-level File Access Open
To create a new file descriptor we need to used the open system call #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> int open(const char *path, int oflags); int open(const char *path, int oflags, mode_t mode);
7
Mode Description ofalgs
The call may also include a combination of the following optional modes in the oflags parameter O_APPEND Place written data at the end of the file O_TRUNC Set the length of the file to zero, discarding exiting contents O_CREAT Creates the file, if necessary, with permissions given in mode Mode Description O-RDONLY Open for read-only O_WRONLY Open for write-only O_RDWR Open for reading and writing
8
#include <fcntl.h>
#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> int main (int argc, char* argv[]) { const char* const filename = argv[1]; int fd = open (filename, O_RDONLY); printf (“in process %d, file descriptor %d is open to %s\n”, (int) getpid (), (int) fd, filename); while (1); return 0; }
9
Low-level File Access Read #include <unistd.h>
size_t read(int fildes, void *buf, size_t nbytes); It returns the number of data bytes actually read, which my be less than the number requested If a read call returns 0, it had nothing to read; it reached the end of the file If a read call returns -1, an error occurs
10
Low-level File Access #include <unistd.h>
write #include <unistd.h> size_t write(int fildes, const void *buf, size_t nbytes); The write system call arranges for the first nbytes bytes from buf to be written to the file associated with the file descriptor fildes. It returns the number of bytes actually written This may be less than nbytes if there has been an error in the file descriptor, of if the underlying device driver is sensitive to block size If the function return 0, it means no data was written, if -1, there has been an error in the write call and the error will be specified in the errno global variable
11
Low-level File Access close #include <unistd.h>
int close(int fildes); We use to terminate the association between a file descriptor, fildes, and its file The file descriptor becomes available for reuse It returns 0 if successful and -1 on error It is important to check the return result from close since some file systems, particularly networked ones, may not report an error writing to a file until the file is closed
12
#include <stdio.h>
#include <stdlib.h> #include <errno.h> #include <unistd.h> int main() { int pfds[2]; char buf[30]; if (pipe(pfds) == -1) { perror("pipe"); exit(1); } printf("writing to file descriptor #%d\n", pfds[1]); write(pfds[1], "test", 5); printf("reading from file descriptor #%d\n", pfds[0]); read(pfds[0], buf, 5); printf("read \"%s\"\n", buf);
13
#include <stdio.h>
#include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { int pfds[2]; char buf[30]; pipe(pfds); if (!fork()) { printf(" CHILD: writing to the pipe\n"); write(pfds[1], "test", 5); printf(" CHILD: exiting\n"); exit(0); } else { printf("PARENT: reading from pipe\n"); read(pfds[0], buf, 5); printf("PARENT: read \"%s\"\n", buf); wait(NULL); }
14
// The 'consumer' program, pipe4
// The 'consumer' program, pipe4.c, that reads the data is much simpler. // The program works with next slide’s codes #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int data_processed; char buffer[BUFSIZ + 1]; int file_descriptor; memset(buffer, '\0', sizeof(buffer)); sscanf(argv[1], "%d", &file_descriptor); data_processed = read(file_descriptor, buffer, BUFSIZ); printf("%d - read %d bytes: %s\n", getpid(), data_processed, buffer); exit(EXIT_SUCCESS); }
15
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { int data_processed; int file_pipes[2]; const char some_data[] = "123"; char buffer[BUFSIZ + 1]; pid_t fork_result; memset(buffer, '\0', sizeof(buffer)); if (pipe(file_pipes) == 0) { fork_result = fork(); if (fork_result == (pid_t)-1) { fprintf(stderr, "Fork failure"); exit(EXIT_FAILURE); } if (fork_result == 0) { sprintf(buffer, "%d", file_pipes[0]); (void)execl("pipe4", "pipe4", buffer, (char *)0); else { data_processed = write(file_pipes[1], some_data, strlen(some_data)); printf("%d - wrote %d bytes\n", getpid(), data_processed); exit(EXIT_SUCCESS);
16
pipes 與 dup 的關係 dup (int file_descriptor) The dup always returns a new file descriptor using the lowest available number.
17
#include <stdio.h>
#include <stdlib.h> #include <unistd.h> int main() { int pfds[2]; pipe(pfds); if (!fork()) { close(1); /* close normal stdout */ dup(pfds[1]); /* make stdout same as pfds[1] */ close(pfds[0]); /* we don't need this */ execlp("ls", "ls", NULL); } else { close(0); /* close normal stdin */ dup(pfds[0]); /* make stdin same as pfds[0] */ close(pfds[1]); /* we don't need this */ execlp("wc", "wc", "-l", NULL); }
18
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { int data_processed; int file_pipes[2]; const char some_data[] = "123"; pid_t fork_result; if (pipe(file_pipes) == 0) { fork_result = fork(); if (fork_result == (pid_t)-1) { fprintf(stderr, "Fork failure"); exit(EXIT_FAILURE); } if (fork_result == (pid_t)0) { close(0); dup(file_pipes[0]); close(file_pipes[0]); close(file_pipes[1]); execlp("od", "od", "-c", (char *)0);
19
else { close(file_pipes[0]); data_processed = write(file_pipes[1], some_data, strlen(some_data)); close(file_pipes[1]); printf("%d - wrote %d bytes\n", (int)getpid(), data_processed); } exit(EXIT_SUCCESS);
20
After the call to fork: When the program is rady to transfer data:
21
dup2 () Using the dup2 call, you can equate one file
descriptor with another. dup2 (fd, STDIN_FILENO);
22
#include <stdio.h>
#include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main () { int fds[2]; pid_t pid; /* Create a pipe. File descriptors for the two ends of the pipe are placed in fds. */ pipe (fds); /* Fork a child process. */ pid = fork (); if (pid == (pid_t) 0) { /* This is the child process. Close our copy of the write end of the file descriptor. */ close (fds[1]); /* Connect the read end of the pipe to standard input. */ dup2 (fds[0], STDIN_FILENO); /* Replace the child process with the “sort” program. */ execlp (“sort”, “sort”, 0); }
23
else { /* This is the parent process. */ FILE* stream; /* Close our copy of the read end of the file descriptor. */ close (fds[0]); /* Convert the write file descriptor to a FILE object, and write to it. */ stream = fdopen (fds[1], “w”); fprintf (stream, “This is a test.\n”); fprintf (stream, “Hello, world.\n”); fprintf (stream, “My dog has fleas.\n”); fprintf (stream, “This program is great.\n”); fprintf (stream, “One fish, two fish.\n”); fflush (stream); close (fds[1]); /* Wait for the child process to finish. */ waitpid (pid, NULL, 0); } return 0;
24
FIFO A FIFO is a named pipe, that is, a pipe with a name in the file system. FIFO is a special kind of file. In fact it is simply a place where different processes (not necessarily have parent-child relation) can communicate. If O_NONBLOCK is specified, the open for reading returns immediately, but the open for write-only will have runtime error.
25
FIFO From inside a program, we can use two different calls. These are:
26
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> int main() { int res = mkfifo("my_fifo", 0777); if (res == 0) printf("FIFO created\n"); exit(EXIT_SUCCESS); } $ ls –al my_fifo $cat < my_fifo & $ echo “abcdefg” > my_fifo $ cat my_fifo
27
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "my_fifo" int main(int argc, char *argv[]) { int res; int open_mode = 0; int i; if (argc < 2) { fprintf(stderr, "Usage: %s <some combination of\ O_RDONLY O_WRONLY O_NONBLOCK>\n", *argv); exit(EXIT_FAILURE); } // Assuming that the program passed the test, we now set the value of open_mode // from those arguments.
28
for(i = 1; i < argc; i++) {
if (strncmp(*++argv, "O_RDONLY", 8) == 0) open_mode |= O_RDONLY; if (strncmp(*argv, "O_WRONLY", 8) == 0) open_mode |= O_WRONLY; if (strncmp(*argv, "O_NONBLOCK", 10) == 0) open_mode |= O_NONBLOCK; } // We now check whether the FIFO exists and create it if necessary. // Then the FIFO is opened and output given to that effect while the program // catches forty winks. Last of all, the FIFO is closed. if (access(FIFO_NAME, F_OK) == -1) { res = mkfifo(FIFO_NAME, 0777); if (res != 0) { fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE);
29
printf("Process %d opening FIFO\n", getpid());
res = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), res); sleep(5); if (res != -1) (void)close(res); printf("Process %d finished\n", getpid()); exit(EXIT_SUCCESS); } $ ./fifo2 O_RDONLY & $./fifo2 O_WRONLY $./fifo2 O_RDONLY O_NONBLOCK &
30
//fifo3.c #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF #define TEN_MEG (1024 * 1024 * 10) int main() { int pipe_fd; int res; int open_mode = O_WRONLY; int bytes_sent = 0; char buffer[BUFFER_SIZE + 1]; if (access(FIFO_NAME, F_OK) == -1) { res = mkfifo(FIFO_NAME, 0777); if (res != 0) { fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE); } printf("Process %d opening FIFO O_WRONLY\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd);
31
if (pipe_fd != -1) { while(bytes_sent < TEN_MEG) { res = write(pipe_fd, buffer, BUFFER_SIZE); if (res == -1) { fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE); } bytes_sent += res; (void)close(pipe_fd); else { printf("Process %d finished\n", getpid()); exit(EXIT_SUCCESS);
32
//fifo4.c #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF int main() { int pipe_fd; int res; int open_mode = O_RDONLY; char buffer[BUFFER_SIZE + 1]; int bytes_read = 0; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opening FIFO O_RDONLY\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd);
33
if (pipe_fd != -1) { do { res = read(pipe_fd, buffer, BUFFER_SIZE); bytes_read += res; } while (res > 0); (void)close(pipe_fd); } else { exit(EXIT_FAILURE); printf("Process %d finished, %d bytes read\n", getpid(), bytes_read); exit(EXIT_SUCCESS); $ ./fifo3 & $. Time ./fifo4
34
popen and pclose the simplest way of passing data between two programs
The popen function allows a program to invoke another program as a new process and either pass data to or receive data from it. When the process started with popen has finished, we can close the file stream associated with it using pclose.
36
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { FILE *read_fp; char buffer[BUFSIZ + 1]; int chars_read; memset(buffer, '\0', sizeof(buffer)); read_fp = popen("uname -a", "r"); if (read_fp != NULL) { chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); if (chars_read > 0) { printf("Output was:-\n%s\n", buffer); } pclose(read_fp); exit(EXIT_SUCCESS); exit(EXIT_FAILURE);
37
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> int main() { FILE *write_fp; char buffer[BUFSIZ + 1]; sprintf(buffer, "Once upon a time, there was...\n"); write_fp = popen("od -c", "w"); if (write_fp != NULL) { fwrite(buffer, sizeof(char), strlen(buffer), write_fp); pclose(write_fp); exit(EXIT_SUCCESS); } exit(EXIT_FAILURE);
38
#include <unistd.h>
#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { FILE *read_fp; char buffer[BUFSIZ + 1]; int chars_read; memset(buffer, '\0', sizeof(buffer)); read_fp = popen("ps -ax", "r"); if (read_fp != NULL) { chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); while (chars_read > 0) { buffer[chars_read - 1] = '\0'; printf("Reading:-\n %s\n", buffer); } pclose(read_fp); exit(EXIT_SUCCESS); exit(EXIT_FAILURE);
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.