1. Historically ,they have been half duplex (i.e., data flows in only one direction). Some systems now provide full-duplex pipes, but for maximum portability ,we should never assume that this is the case.
2. Pipes can be used only between processes that have a common ancestor. Normally,a pipe is created by a process, that process calls fork,and the pipe is used between the parent and the child
#include <unistd.h> int pipe(int fd[2] );Returns: 0 if OK,−1 on error
1. If we read from a pipe whose write end has been closed, read re turns 0 to indicate an end of file after all the data has been read.
2. If we write to a pipe whose read end has been closed, the signal SIGPIPE is generated. If we either ignore the signal or catch it and return from the signal handler, write returns −1 with errno set to EPIPE
/*************************************************************************************** code writer :EOF code date : 2014.04.10 e-mail : [email protected] code purpose : Just a changed and test demo. If there is something wrong with my code, please touch me by e-mail. If you know about why there is no competition between the child process and parent process when they "read" and "write", please touch me. I am very happy to share my code with you. Wish it could help you to understand pipe. Thank you. ***************************************************************************************/ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #define MAXLINE 4096 int main() { int n; int fd[2]; pid_t pid; char line[MAXLINE]; if(pipe(fd) < 0) { printf("pipe error\n"); } if((pid = fork()) < 0) { printf("fork error\n"); } else if( pid > 0) { sleep(1); //It's interesting that let child go first //and I found that the read from pipe would wait for pipe input finished close(fd[0]); write(fd[1],"hello world!\n",13); waitpid(-1,NULL,0);//It's neccessary to wait for child to terminate. } else { close(fd[1]); n = read(fd[0],line,MAXLINE); write(STDOUT_FILENO,line,n); } return 0; }
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/wait.h> #include <fcntl.h> #define DEF_PAGER "/bin/more" #define MAXLINE 4096 int main(int argc,char* argv[]) { int n; int fd[2]; pid_t pid; char *pager,*argv0; char line[MAXLINE]; FILE *fp; printf("%d\n",STDIN_FILENO); if(argc != 2) { printf("usage: a.out <pathname>\n"); return 0; } if((fp = fopen(argv[1],"r")) < 0) { printf("can't open %s\n",argv[1]); return 0; } if(pipe(fd) < 0) { printf("pipe error\n"); } if((pid = fork()) < 0) { printf("fork error\n"); } else if(pid > 0) { close(fd[0]); while(fgets(line,MAXLINE,fp) != NULL) { n = strlen(line); if(write(fd[1],line,n) != n) { printf("write error to pipe\n"); } } if(ferror(fp)) { printf("fgets error\n"); } close(fd[1]); if(waitpid(pid, NULL,0) < 0) { printf("waitpid error\n"); } exit(0); } else { close(fd[1]); if(fd[0] != STDIN_FILENO) { if(dup2(fd[0],STDIN_FILENO) != STDIN_FILENO) { printf("dup2 error to stdin\n"); } close(fd[0]); } if((pager = getenv("PAGER")) == NULL) { pager = DEF_PAGER; } if((argv0 = strrchr(pager,'/')) != NULL) { argv0++; } else { argv0 = pager; } if(execl(pager,argv0,NULL) < 0) { printf("execl error for %s\n",pager); } return 0; } return 0; }
close(fd[1]); if(fd[0] != STDIN_FILENO) { if(dup2(fd[0],STDIN_FILENO) != STDIN_FILENO) { printf("dup2 error to stdin\n"); } close(fd[0]); }
#include <stdio.h> #include <fcntl.h> static pfd1[2],pfd2[2]; void TELL_WAIT(void) { if(pipe(fpd1) < 0 || pipe(pfd2) < 0) { printf("pipe error\n"); } } void TELL_PARENT(void)//tell to parent { if(write(pfd2[1],"c",1) != 1) { printf("write error\n"); } } void WAIT_PARENT(void)//wait for parent { char c; if(read(pfd1[0],&c,1) != 1) { printf("read error\n"); } if(c != 'p') { printf("WAIT_PARENT: incorrect data\n"); } } void TELL_CHILD(pid_t pid)//tell to child { if(write(pfd1[1],"p",1) != 1) { printf("write error\n"); } } void WAIT_CHILD(void)//wait for child { char c; if(read(pdf2[0],&c,1) != 1) { printf("read error\n"); } if(c != 'c') { printf("WAIT_CHILD : incorrect data\n"); } }
#include <stdio.h> FILE *popen(const char *cmdstring,const char *type ); Returns: file pointer if OK, NULL on error int pclose(FILE *fp ); Returns: termination status ofcmdstring,or −1 on error
#include <stdio.h> #include <sys/wait.h> #include <fcntl.h> #define PAGER "${PAGER:-more}" #define MAXLINE 4096 int main(int argc,char* argv[]) { char line[MAXLINE]; FILE *fpin,*fpout; if(argc != 2) { printf("usage: a.out <pathname>\n"); } if((fpin = fopen(argv[1],"r")) == NULL) { printf("fopen error\n"); } if((fpout = popen(PAGER,"w")) == NULL)//single direction pipe { printf("popen error\n"); } while(fgets(line,MAXLINE,fpin) != NULL) { if(fputs(line,fpout) == EOF) { printf("fputs error to pipe"); } } if(ferror(fpin)) { printf("fgets error\n"); } if(pclose(fpout) == -1) { printf("pclose error\n"); } return 0; }
#include <stdio.h>
#include <ctype.h>
int main()
{
int c;
while((c = getchar()) != EOF)
{
if(isupper(c))
{
c = tolower(c);
}
if(putchar(c) == EOF)
{
printf("output error\n");
}
if(c == '\n')
{
fflush(stdout);
}
}
return 0;
}
#include <stdio.h> #include <sys/wait.h> #include <unistd.h> #define MAXLINE 4096 int main() { char line[MAXLINE]; FILE* fpin; if((fpin = popen("./myuclc","r")) == NULL) { printf("popen error\n"); } for(;;) { fputs("prompt >",stdout); fflush(stdout); if(fgets(line,MAXLINE,fpin) == NULL) { break; } if(fputs(line,stdout) == EOF) { printf("fputs error to pipe\n"); } } if(pclose(fpin) == -1) { printf("pclose error\n"); } putchar('\n'); return 0; }
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define MAXLINE 4096
int main()
{
int n,int1,int2;
char line[MAXLINE];
while((n = read(STDIN_FILENO,line,MAXLINE)) > 0)
{
line[n] = 0;
if(sscanf(line,"%d%d",&int1,&int2) == 2)
{
sprintf(line,"%d\n",int1+int2);
n = strlen(line);
if(write(STDOUT_FILENO,line,n) != n)
{
printf("write error\n");
}
}
else
{
if(write(STDOUT_FILENO,"invalid args\n",13) != 13)
{
printf("write error\n");
}
}
}
return 0;
}
#include <stdio.h> #include <string.h> #include <signal.h> #include <unistd.h> #include <fcntl.h> #define MAXLINE 4096 static void sig_pipe(int signo) { printf("SIGPIPE caught\n"); } int main() { int n,fd1[2],fd2[2]; pid_t pid; char line[MAXLINE]; struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sig_pipe; sigaddset(&sa.sa_mask,SIGPIPE); if(sigaction(SIGPIPE,&sa,NULL) < 0) { printf("sigaction error\n"); return 0; } if(pipe(fd2) < 0 || pipe(fd1) < 0) { printf("pipe error\n"); return 0; } if((pid = fork()) < 0) { printf("fork error\n"); } else if(pid > 0) { close(fd1[0]); close(fd2[1]); while(fgets(line,MAXLINE,stdin) != NULL) { n = strlen(line); if(write(fd1[1],line,n) != n) { printf("write error\n"); } if(read(fd2[0],line,MAXLINE) < 0)//Is there some problems that we use the same buffer--line { printf("read error from pipe\n"); } if(n == 0) { printf("child close pipe\n"); break; } line[n] = 0; if(fputs(line,stdout) == EOF) { printf("fputs error\n"); } } if(ferror(stdin)) { printf("fgets error\n"); } /* if(waitpid(pid,NULL,0) < 0) { printf("waitpid error\n"); } */ return 0; } else { close(fd1[1]); close(fd2[0]); if(fd1[0] != STDIN_FILENO) { if(dup2(fd1[0],STDIN_FILENO) != STDIN_FILENO) { printf("dup2 error to stdin\n"); } close(fd1[0]); } if(fd2[1] != STDOUT_FILENO) { if(dup2(fd2[1],STDOUT_FILENO) != STDOUT_FILENO) { printf("dup2 error\n"); } close(fd2[1]); } while(fgets(line,MAXLINE,stdin) != NULL) { fputs(line,stdout); } // pause(); /* if(waitpid(getppid(),NULL,0) < 0) { printf("waitpid error\n"); } if(execl("./add2","add2",NULL) < 0) { printf("execl error\n"); } */ } return 0; }APUE没给输出,只是大致说了一下,但是我debug的时候,不管怎么调都是会触发SIGPIPE。管道莫名其妙的就断了
#include <stdio.h> #define MAXLINE 4096 int main() { int int1,int2; char line[MAXLINE]; while(fgets(line,MAXLINE,stdin) != NULL) { if(sscanf(line,"%d%d",&int1,&int2) == 2) { if(printf("%d\n",int1+int2) == EOF) { printf("printf error\n"); } } else { if(printf("invalid args\n") == EOF) { printf("printf error\n"); } } } return 0; }
#include <sys/stat.h> int mkfifo(const char * path ,mode_tmode); int mkfifoat(int fd ,const char *path ,mode_tmode); Both return: 0 if OK, −1 on error
•In the normal case (without O_NONBLOCK), an open for read-only blocks until some other process opens the FIFO for writing. Similarly,an open for write-only blocks until some other process opens the FIFO for reading.
•If O_NONBLOCK is specified, an open for read-only returns immediately.But an open for write-only returns −1 with errno set to ENXIO if no process has the FIFO open for reading.
1. FIFOs are used by shell commands to pass data from one shell pipeline to another without creating intermediate temporary files.
2. FIFOs are used as rendezvous points in client–server applications to pass data between the clients and the servers.
#include <sys/ipc.h> key_t ftok(const char * path ,int id ); Returns: key if OK, (key_t)−1 on error
/* Mode bits for `msgget', `semget', and `shmget'. */
#define IPC_CREAT 01000 /* Create key if key does not exist. */
#define IPC_EXCL 02000 /* Fail if key exists. */
#define IPC_NOWAIT 04000 /* Return error on wait. */
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
#define IPC_STAT 2 /* Get `ipc_perm' options. */
#ifdef __USE_GNU
# define IPC_INFO 3 /* See ipcs. */
#endif
/* Special key values. */
#define IPC_PRIVATE ((__key_t) 0) /* Private key. */
/* Data structure used to pass permission information to IPC operations. */
struct ipc_perm
{
__key_t __key; /* Key. */
__uid_t uid; /* Owner's user ID. */
__gid_t gid; /* Owner's group ID. */
__uid_t cuid; /* Creator's user ID. */
__gid_t cgid; /* Creator's group ID. */
unsigned short int mode; /* Read/write permission. */
unsigned short int __pad1;
unsigned short int __seq; /* Sequence number. */
unsigned short int __pad2;
__syscall_ulong_t __unused1;
__syscall_ulong_t __unused2;
};
struct msqid_ds { struct ipc_perm msg_perm; /* structure describing operation permission */ __time_t msg_stime; /* time of last msgsnd command */ #ifndef __x86_64__ unsigned long int __unused1; #endif __time_t msg_rtime; /* time of last msgrcv command */ #ifndef __x86_64__ unsigned long int __unused2; #endif __time_t msg_ctime; /* time of last change */ #ifndef __x86_64__ unsigned long int __unused3; #endif __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ __pid_t msg_lspid; /* pid of last msgsnd() */ __pid_t msg_lrpid; /* pid of last msgrcv() */ __syscall_ulong_t __unused4; __syscall_ulong_t __unused5; };
#include <sys/msg.h> int msgget(key_t key,int flag); Returns: message queue ID if OK, −1 on error #include <sys/msg.h> int msgctl(int msqid,int cmd ,struct msqid_ds *buf ); Returns: 0 if OK,−1 on error #include <sys/msg.h> int msgsnd(int msqid,const void *ptr,size_tnbytes ,int flag); Returns: 0 if OK,−1 on error
/* Data structure describing a shared memory segment. */ struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ size_t shm_segsz; /* size of segment in bytes */ __time_t shm_atime; /* time of last shmat() */ #ifndef __x86_64__ unsigned long int __unused1; #endif __time_t shm_dtime; /* time of last shmdt() */ #ifndef __x86_64__ unsigned long int __unused2; #endif __time_t shm_ctime; /* time of last change by shmctl() */ #ifndef __x86_64__ unsigned long int __unused3; #endif __pid_t shm_cpid; /* pid of creator */ __pid_t shm_lpid; /* pid of last shmop */ shmatt_t shm_nattch; /* number of current attaches */ __syscall_ulong_t __unused4; __syscall_ulong_t __unused5; };
/* Mode bits for `msgget', `semget', and `shmget'. */ #define IPC_CREAT 01000 /* Create key if key does not exist. */ #define IPC_EXCL 02000 /* Fail if key exists. */ #define IPC_NOWAIT 04000 /* Return error on wait. */ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ #define IPC_STAT 2 /* Get `ipc_perm' options. */ #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif /* Special key values. */ #define IPC_PRIVATE ((__key_t) 0) /* Private key. */
#include <sys/shm.h>
int shmget(key_t key,size_tsize ,int flag);
Returns: shared memory ID if OK,−1 on error
The size parameter is the size of the shared memory segment in bytes.如果那个flag不用就置0就可以了
#include <sys/shm.h>
int shmctl(int shmid ,int cmd ,struct shmid_ds *buf );
Returns: 0 if OK,−1 on error
IPC_STAT
Fetch the shmid_ds structur efor this segment, storing it in the structure pointed to by buf.
IPC_SETSet the following three fields from the structure pointed to by buf in the shmid_ds structure associated with this shared memory segment: shm_perm.uid, shm_perm.gid,and shm_perm.mode .This command can be executed only by a process whose effective user ID equals shm_perm.cuid or shm_perm.uid or by a process with superuser privileges.
IPC_RMIDRemove the shared memory segment set from the system. Since an attachment count is maintained for shared memory segments (the shm_nattch field in the shmid_ds structure), the segment is not removed until the last process using the segment terminates or detaches it. Regardless of whether the segment is still in use, the segment’s identifier is immediately removed so that shmat can nolonger attach the segment. This command can be executed only by a process whose effective user ID equals shm_perm.cuid or shm_perm.uid or by a process with superuser privileges
Once a shared memory segment has been created, a process attaches it to its address space by calling shmat
#include <sys/shm.h>
void *shmat(intshmid ,const void *addr ,int flag);
Returns: pointer to shared memory segment if OK,−1 on error
•If addr is 0, the segment is attached at the first available address selected by the kernel. This is the recommended technique.
•If addr is nonzero and SHM_RNDis not specified, the segment is attached at the address given by addr .
•If addr is nonzero and SHM_RND is specified, the segment is attached at the address given by ( addr − (addr modulus SHMLBA)). The SHM_RND command stands for ‘‘round.’’ SHMLBA stands for ‘‘low boundary address multiple’ ’and is always a power of 2. What the arithmetic does is round the address down to the next multiple of SHMLBA.
#include <sys/shm.h>
int shmdt(const void *addr );
Returns: 0 if OK,−1 on error
#include <stdio.h> #include <stdlib.h> #include <sys/shm.h> #define ARRAY_SIZE 4000 #define MALLOC_SIZE 100000 #define SHM_SIZE 100000 #define SHM_MODE 0600 //usr read/write mode char array[ARRAY_SIZE]; int main() { int shmid; char *ptr,*shmptr; printf("array[] from %lx to %lx\n",(unsigned long)&array[0],\ (unsigned long)&array[ARRAY_SIZE]); printf("stack around %lx \n",(unsigned long)&shmid); if((ptr = malloc(MALLOC_SIZE)) == NULL) { printf("malloc error\n"); } printf("malloced from %lxto %lx\n",(unsigned long)ptr,\ (unsigned long)ptr+MALLOC_SIZE); if((shmid = shmget(IPC_PRIVATE,SHM_SIZE,SHM_MODE)) < 0) { printf("shmget error\n"); } if((shmptr = shmat(shmid,0,0)) == NULL) { printf("shmat error\n"); } printf("shared memory attached from %lx to %lx\n",(unsigned long)shmptr,\ (unsigned long)shmptr+SHM_SIZE); if(shmctl(shmid,IPC_RMID,0) < 0) { printf("shmctl error\n"); } return 0; }
#include <stdio.h> #include <fcntl.h> #include <sys/mman.h> #define NLOOPS 1000 #define SIZE sizeof(long) static int update(long * ptr) { return (*ptr)++; } int main() { int fd,i,counter; pid_t pid; void * area; int fd1[2],fd2[2]; if((fd = open("/dev/zero",O_RDWR)) < 0) { printf("open error\n"); } if((area = mmap(0,SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED) { printf("mmap error\n"); } close(fd); if(pipe(fd1) < 0 || pipe(fd2) < 0) { printf("pipe error\n"); } if((pid = fork()) < 0) { printf("fork error\n"); } else if(pid > 0) { close(fd1[0]); close(fd2[1]); int c; for(i = 0;i < NLOOPS;i++) { if((counter = update((long*) area)) != i) { printf("parent: expect %d,got %d\n",i,counter); } // TELL_CHILD(pid); if(write(fd1[1],"p",1) != 1) { printf("write error\n"); } // WAIT_CHILD(); if(read(fd2[0],&c,1) != 1) { printf("read error\n"); } } } else { close(fd1[1]); close(fd2[0]); for(i = 0;i < NLOOPS;i++) { if((counter = update((long*) area)) != i) { printf("parent: expect %d,got %d\n",i,counter); } // TELL_PARENT(); if(write(fd2[1],"c",1) != 1) { printf("write error\n"); } } } return 0; }
#include <stdio.h> #include <fcntl.h> #include <sys/mman.h> #define NLOOPS 1000 #define SIZE sizeof(long) static int update(long * ptr) { return (*ptr)++; } int main() { int fd,i,counter; pid_t pid; void * area; int fd1[2],fd2[2]; /* if((fd = open("/dev/zero",O_RDWR)) < 0) { printf("open error\n"); } */ if((area = mmap(0,SIZE,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0)) == MAP_FAILED) { printf("mmap error\n"); } // close(fd); if(pipe(fd1) < 0 || pipe(fd2) < 0) { printf("pipe error\n"); } if((pid = fork()) < 0) { printf("fork error\n"); } else if(pid > 0) { close(fd1[0]); close(fd2[1]); int c; for(i = 0;i < NLOOPS;i++) { if((counter = update((long*) area)) != i) { printf("parent: expect %d,got %d\n",i,counter); } // TELL_CHILD(pid); if(write(fd1[1],"p",1) != 1) { printf("write error\n"); } // WAIT_CHILD(); if(read(fd2[0],&c,1) != 1) { printf("read error\n"); } } } else { close(fd1[1]); close(fd2[0]); for(i = 0;i < NLOOPS;i++) { if((counter = update((long*) area)) != i) { printf("parent: expect %d,got %d\n",i,counter); } // TELL_PARENT(); if(write(fd2[1],"c",1) != 1) { printf("write error\n"); } } } return 0; }