|
|||||
| | |||||
here we are again in operating systems
in chapter 7 of Unix Systems Programming: pipes
--unnammed pipes
--named pipes
--popen
--token ring
pipes occur at the kernel level, not at the user level, so that the data
transferred are transferred through the kernel
commandline pipes redirect from stdout to another special files' stdin
pipes are half-duplex models, only, please read the section in
http://www.cim.mcgill.ca/~franco/OpSys-304-427/lecture-notes/node28.html
where he says
"The reason for the last black dot (appropriately called
``bullet'' by typographers), is that the kernel uses just one internal buffer
for temporary storage of the flowing data, hence what goes in one direction
overwrites whatever is a naive programmer tries to send backward. So, just to
stress the concept once more: pipes make half-duplex, i.e. one-way,
communication channels."
int fd[2];
pipe(fd) - unnamed pipe, If the pipe is created succesfully, then its
readable end is fildes[0], while fildes[1] is the writable one.
pipes (when no longer usable) are destroyed --- cannot be used at system level
FIFO: named pipes; unlike pipe(fd) persist
appear in dir listings with first char == p
if nothing is available for reading on a pipe, read will hang
so, need to write to pipe before reading from it.
perror("failed to create myfifo");
mkfifo is also a shell command
<url:namedpipes/parentchildfifo.c:parentchildfifo.c>
opens a pipe and calls two functions dofifochild and dofifoparent
<url:namedpipes/dofifochild.c:dofifochild.c>: this tries to open fifo, checking signal ( errno == EINTR)
else creates an id string
uses snprintf to copy into a buffer
first opens pipe with
fd = open(fifoname, O_RDONLY)) == -1 && (errno == EINTR)) ;
which is same code as opening any file
open pipe before fork only in order that child can use that pipe
doesn't apply to mkfifo as the pipe exists as a file
program note: in printf %.s means means take value from the value string from printf valarg array at end of printf statement
FILE *popen(char command, char type);
Opens a stream-oriented pipe between the current process and program command,
taking care of all the dirty jobs: forking, duplicating file descriptors,
executing command, etc
see http://www.cim.mcgill.ca/~franco/OpSys-304-427/lecture-notes/node28.html
at the very bottom
server: waits for requests for clients
client: requests service from server
a client can be both client and server
the two programs here are an example of IPC communication where the 2 processes are on the same machine
<url:pipeserver.c:pipeserver.c>: requires fifoname on CLI. creates if doesn't exist, opens for reading, does copyfile to STDOUT_FILENO.
<url:pipeclient.c:pipeclient.c>: requires filename from CLI. time(NULL).
snprintf: like sprintf; the printf variants which writes to a buffer.
strncpy: takes the format spec and writes to buffer, but limits output to "n" size, which protects from buffer overflows.
note PIPE_BUF is a standard constant proably in unistd.h
note pipes always make what they write strings by appending a '\0'
when writing to buff will wait if size of buffer > SIZE_BUF
PIPE_BUF is always > 256 but usually larger
atomic: sth which can't be split up; no interruptions writing to pipe if concurrently writing by two processes at the same time
a write of at most PIPE_BUF bytes to a pipe or FIFO is atomic
not true of reads nor of writes to the terminal, which means, if pipe has a,b,c,d,e,f,g and process reads 3 bytes and at the same time another process reads 3 bytes means almost anything can happen. Any combination of those bytes is possible.
not good when important data structures (ie kernel data structures) are being changed -- context switch time is too often cause daily crash.
"The projects of this chapter explore pipes, forks and redirection in the context of a ring or process."
this is an example of using pipes to communicate between parent and process.
in this case is a ring of processes which must read/write in a circle to pipes in their neighbors
for how many processes?
pipe (fd); // creates fd table entries for fd[3] and fd[4] but we can't know their array number entries
dup2(fd[0], STDIN_FILENO); //
dup2(fd[1], STDOUT_FILENO);
close(fd[0]); // close writing end
close(fd[1]); // close reading end
pipe(fd);
// close the reading end in the parent and the writing end in the child, if
// you want to send data from the parent to the child;
this does
dup fd#3 -> fd#0 (read)
dup fd#4 -> fd#1 (write)
flow: create 2 pipes, then fork.... so child has same file descriptor table as its parent process, so they can read/write the same pipes.
this has a two-directional flow of communication, all processes A and B can read/write those pipes
he doesn't want process b to read from pipeA. he makes it unidirectional flow only.
if (childpid == fork()) == -1)
......
if (childpid)
break;
end chapter 7 in USP
| Leave a Reply |