1、创建一个简单的管道,可以使用系统调用pipe()。它接受一个参数,也就是一个包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。系统调用:pipe();原型:int pipe(int fd2);返回值:如果系统调用成功,返回0。如果系统调用失败返回-1:errno=EMFILE(没有空亲的文件描述符) EMFILE(系统文件表已满) EFAULT(fd数组无效)注意:fd0用于读取管道,fd1用于写入管道。图见附件管道的创建#includeerrno.hstdio.hstdlib.hint main()int pipe
2、_fd2;if(pipe(pipe_fd)pid_t pid;char buf_r100;char* p_wbuf;int r_num;memset(buf_r,0,sizeof(buf_r);数组中的数据清0;if(pid=fork()=0)nsleep(2);if(r_num=read(pipe_fd0,buf_r,100)%d numbers read from be pipe is %sn,r_num,buf_r);exit(0);else if(pidif(write(pipe_fd1,Hello,5)!=-1)parent write success! Pipeparent wir
3、te2 succes!sleep(3);waitpid(pid,NULL,0);标准流管道与linux中文件操作有文件流的标准I/O一样,管道的操作也支持基于文件流的模式。接口函数如下:库函数:popen();FILE *open (char *command,char *type);如果成功,返回一个新的文件流。如果无法创建进程或者管道,返回NULL。管道中数据流的方向是由第二个参数type控制的。此参数可以是r或者w,分别代表读或写。但不能同时为读和写。在Linux 系统下,管道将会以参数type中第一个字符代表的方式打开。所以,如果你在参数type中写入rw,管道将会以读的方式打开。使用
4、popen()创建的管道必须使用pclose()关闭。其实,popen/pclose和标准文件输入/输出流中的fopen()/fclose()十分相似。pclose();int pclose(FILE *stream);返回系统调用wait4()的状态。如果stream无效,或者系统调用wait4()失败,则返回-1。注意此库函数等待管道进程运行结束,然后关闭文件流。库函数pclose()在使用popen()创建的进程上执行wait4()函数,它将破坏管道和文件系统。流管道的例子。fcntl.h#define BUFSIZE 1024int main()FILE *fp;char *cmd=p
5、s -ef;char bufBUFSIZE;bufBUFSIZE=0if(fp=popen(cmd,r)=NULL)perror(popenwhile(fgets(buf,BUFSIZE,fp)!=NULL)%s,buf);pclose(fp);命名管道(FIFO)基本概念命名管道和一般的管道基本相同,但也有一些显著的不同:A、命名管道是在文件系统中作为一个特殊的设备文件而存在的。B、不同祖先的进程之间可以通过管道共享数据。C、当共享管道的进程执行完所有的I/O操作以后,命名管道将继续保存在文件系统中以便以后使用。管道只能由相关进程使用,它们共同的祖先进程创建了管道。但是,通过FIFO,不相关
6、的进程也能交换数据。命名管道创建与操作命名管道创建sys/types.hsys/stat.hint mkfifo(const char *pathname,mode_t mode);返回:若成功则为0,若出错返回-1一旦已经用mkfifo创建了一个FIFO,就可用open打开它。确实,一般的文件I/O函数(close,read,write,unlink等)都可用于FIFO。当打开一个FIFO时,非阻塞标(O_NONBLOCK)产生下列影响:(1)在一般情况中(没有说明O_NONBLOCK),只读打开要阻塞到某个其他进程为写打开此FIFO。类似,为写而打开一个FIFO要阻塞到某个其他进程为读而打
7、开它。(2)如果指一了O_NONBLOCK,则只读打开立即返回。但是,如果没有进程已经为读而打开一个FIFO,那么只写打开将出错返回,其errno是ENXIO。类似于管道,若写一个尚无进程为读而打开的FIFO,则产生信号SIGPIPE。若某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志。FIFO相关出错信息:EACCES(无存取权限)EEXIST(指定文件不存在)ENAMETOOLONG(路径名太长)ENOENT(包含的目录不存在)ENOSPC(文件系统余空间不足)ENOTDIR(文件路径无效)EROFS(指定的文件存在于只读文件系统中)fifo_wr
8、ite.cstring.h#define FIFO /tmp/myfifomain(int argc,char* argv)int fd;int nread;if(mkfifo(FIFO,O_CREAT|O_EXCL)int kill(pid_t pid,int signo);int raise(int signo);两个函数返回:若成功则为0,若出错则为-1。kill的pid参数有四种不同的情况:(1)pid0将信号发送给进程ID为pid的进程。(2)pid=0将信号发送给其进程组ID等于发送进程的进程组ID,而且发送进程有许可权向其发送信号的所有进程。(3)pidint ret;if(pi
9、d=fork()perro(forkif(pid=0)raise(SIGSTOP);else pid=%dn,pid);if(waitpid(pid,NULL,WNOHANG)=0)if(ret=kill(pid,SIGKILL)=0)kill %dnelsekillalarm和pause函数使用alarm函数可以设置一个时间值(闹钟时间),在将来的某个时刻时间值会被超过。当所设置的时间被超过后,产生SIGALRM信号。如果不忽略或不捕捉引信号,则其默认动作是终止该进程。unsigned int alarm(unsigned int secondss);0或以前设置的闹钟时间的余留秒数。参数s
10、econds的值是秒数,经过了指定的seconds秒后产生信号SIGALRM。每个进程只能有一个闹钟时间。如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,则该闹钟时间的余留值作为本次alarm函数调用的值返回。以前登记的闹钟时间则被新值代换。如果有以前登记的尚未超过的闹钟时间,而且seconds值是0,则取消以前的闹钟时间,其余留值仍作为函数的返回值。pause函数使用调用进程挂起直至捕捉到一个信号int pause(void);-1,errno设置为EINTR只有执行了一信号处理程序并从其返回时,pause才返回。alarm.cret=alarm(5);I have
11、been waken up.n,ret);信号的处理当系统捕捉到某个信号时,可以忽略谁信号或是使用指定的处理函数来处理该信号,或者使用系统默认的方式。信号处理的主要方式有两种,一种是使用简单的signal函数,别一种是使用信号集函数组。signal()void (*signal (int signo,void (*func)(int)(int)成功则为以前的信号处理配置,若出错则为SIG_ERRfunc的值是:(a)常数SIGIGN,或(b)常数SIGDFL,或(c)当接到此信号后要调用的的函数的地址。如果指定SIGIGN,则向内核表示忽略此信号(有两个信号SIGKILL和SIGSTOP不能忽
12、略)。如果指定SIGDFL,则表示接到此信号后的动作是系统默认动作。当指定函数地址时,我们称此为捕捉此信号。我们称此函数为信号处理程序(signal handler)或信号捕捉函数(signal-catching funcgion).signal函数原型太复杂了,如果使用下面的typedef,则可以使其简化。type void sign(int);sign *signal(int,handler *);实例见:mysignal.cvoid my_func(int sign_no)if(sign_no=SIGINT)I have get SIGINTnelse if(sign_no=SIGQUIT)I have get SIGQUITnWaiting for signal SIGINT or SIGQUTInsignal(SIGINT,my_func);signal(SIGQUIT,my_func);pasue();信号集函数组我们需要有一个能表示多个信号信号集(signal set)的数据类型。将在sigprocmask()这样的函数中使用这种数据类型,以告诉内核不允许发生该信号集中的信号。信号集函数组包含水量几大模块:创建函数集、登记信号集、检测信号集。创建函数集int sigempty
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1