unix/linux编程实践教程:I/O重定向和管道
2014-09-02 21:14
246 查看
1. 经典的shell编程
监视其他用户的登陆和注销
程序输出:(我通过root用户运行终端,通过另一个用户登陆另一个终端,然后退出,程序显示如下)
2. 经典重定向输出
3. 将文件重定向到stdin和stdout
程序输出:
将文件重定向到stdout:who > userlist。 shell使用进程通过fork产生子进程与子进程调用exec之间的时间间隔来重定向标准输入,输出到文件:
4. 管道编程
在使用pipe函数的时候,pipe[1]为写入端,pipe[0]为读取端。以下程序从标准输入中读取数据,写入pipe[1],然后从pipe[0]读取数据,写出到标准输出端。
我们可以使用fork来共享管道(父子进程共用一个管道):
如何实现:pipe who sort这样的命令?流程如下:
who--->stdin--->(dup)--->pipe[1]--->pipe[0]--->(dup)--->stdin--->sort
对于各种函数的解释,极力推荐APUE
监视其他用户的登陆和注销
#!/bin/sh who | sort > prev while true;do sleep 10 who | sort > curr echo "logged out:" comm -23 prev curr echo "logged in:" comm -13 prev curr mv curr prev done这里解释一下unix的工具comm,可以找出两个文件中共有的行。比较两个文件可以得到三个子集:仅文件1有的行,仅文件2有的行,两者共有的行。
程序输出:(我通过root用户运行终端,通过另一个用户登陆另一个终端,然后退出,程序显示如下)
root@ThinkPad-T430i:/home/leichaojian# vim watch.sh root@ThinkPad-T430i:/home/leichaojian# sh watch.sh logged out: logged in: leichaojian pts/9 2014-09-02 19:36 (:0) logged out: leichaojian pts/9 2014-09-02 19:36 (:0) logged in: ^C
2. 经典重定向输出
#include <stdio.h> int main( int ac, char *av[] ) { int i; printf("number of args:%d, args are:\n", ac); for ( i = 0; i < ac; i++ ){ printf("args[%d] %s\n", i, av[ i ] ); } fprintf(stderr, "this message is sent to stderr.\n"); return 0; }程序运行结果:
leichaojian@ThinkPad-T430i:~$ ./a.out testing > xyz one two 2> oop leichaojian@ThinkPad-T430i:~$ cat xyz number of args:4, args are: args[0] ./a.out args[1] testing args[2] one args[3] two leichaojian@ThinkPad-T430i:~$ cat oop this message is sent to stderr.这里> xyz的位置倒不重要,中间也可以有空格符等。但是2代表的是stderr流,中间不能有空格。所以2和>的中间一定没有空格。
3. 将文件重定向到stdin和stdout
<span style="color:#000000;">#include <stdio.h> #include <fcntl.h> int main( void ) { int fd; char line[ 100 ]; int newfd; fgets( line, 100, stdin ); printf("%s", line ); fgets( line, 100, stdin ); printf("%s", line ); fgets( line, 100, stdin ); printf("%s", line ); fd = open("/etc/passwd", O_RDONLY); #ifdef CLOSE_DUP close( 0 ); newfd = dup( fd ); #else newfd = dup2( fd, 0 ); #endif if ( newfd != 0 ){ fprintf(stderr, "could not open data as fd 0\n"); exit( 1 ); } close( fd ); fgets( line, 100, stdin ); printf("%s", line ); fgets( line, 100, stdin ); printf("%s", line ); fgets( line, 100, stdin ); printf("%s", line ); return 0; }</span>
程序输出:
leichaojian@ThinkPad-T430i:~$ ./a.out hello world hello world i love this world i love this world and i love unix too and i love unix too root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin
将文件重定向到stdout:who > userlist。 shell使用进程通过fork产生子进程与子进程调用exec之间的时间间隔来重定向标准输入,输出到文件:
#include <stdio.h> #include <fcntl.h> int main( void ) { int pid; int fd; printf("about to run who into a file\n"); if ( ( pid = fork() ) == -1 ){ perror("fork"); exit(1); } if ( pid == 0 ){ close( 1 ); fd = open("userlist", O_WRONLY | O_CREAT | O_TRUNC, 0644); execlp("who","who",NULL); perror("execlp"); exit(1); } if ( pid != 0 ){ wait( NULL ); printf("done running who. results in userlist\n"); } return 0; }程序输出:
leichaojian@ThinkPad-T430i:~$ ./a.out about to run who into a file done running who. results in userlist leichaojian@ThinkPad-T430i:~$ cat userlist leichaojian :0 2014-09-02 19:25 (:0) leichaojian pts/0 2014-09-02 19:33 (:0)
4. 管道编程
在使用pipe函数的时候,pipe[1]为写入端,pipe[0]为读取端。以下程序从标准输入中读取数据,写入pipe[1],然后从pipe[0]读取数据,写出到标准输出端。
#include <stdio.h> #include <unistd.h> int main( void ) { int len, i, apipe[ 2 ]; char buf[ BUFSIZ ]; if ( pipe( apipe ) == -1 ){ perror("could not make pipe\n"); exit( 1 ); } printf("got a pipe! it is file descriptors:{%d %d}\n", apipe[ 0 ], apipe[ 1 ] ); while ( fgets( buf, BUFSIZ, stdin ) ){ len = strlen( buf ); if ( write( apipe[ 1 ], buf, len ) != len ){ perror("writing to pipe\n"); break; } for ( i = 0; i < len; i++ ) buf[ i ] = 'X'; len = read( apipe[ 0 ], buf, BUFSIZ ); if ( len == -1 ){ perror( "reading from pipe" ); break; } if ( write( 1, buf, len ) != len ){ perror("writing to stdout\n"); break; } } return 0; }程序输出:
leichaojian@ThinkPad-T430i:~$ ./a.out got a pipe! it is file descriptors:{3 4} hello world hello world i love thisworld i love thisworld and i love unix too and i love unix too ^C
我们可以使用fork来共享管道(父子进程共用一个管道):
#include <stdio.h> #define CHILD_MESS "I want a cookie\n" #define PAR_MESS "testing..\n" #define oops(m, x) {perror(m);exit(x);} int main( void ) { int pipefd[ 2 ]; int len; char buf[ BUFSIZ ]; int read_len; if ( pipe( pipefd ) == -1 ) oops("cannot get a pipe", 1 ); switch( fork() ){ case -1: oops("cannot fork.", 2); case 0: len = strlen( CHILD_MESS); while ( 1 ){ if ( write( pipefd[ 1 ], CHILD_MESS, len ) != len ) oops("write", 3); sleep(5); } default: len = strlen(PAR_MESS); while ( 1 ){ if ( write(pipefd[1], PAR_MESS, len ) != len ) oops("write", 4); sleep(1); read_len = read( pipefd[0], buf, BUFSIZ); if ( read_len <= 0 ) break; write( 1, buf, read_len ); } } return 0; }程序输出:
leichaojian@ThinkPad-T430i:~$ ./a.out testing.. I want a cookie testing.. testing.. testing.. testing.. I want a cookie testing.. testing..
如何实现:pipe who sort这样的命令?流程如下:
who--->stdin--->(dup)--->pipe[1]--->pipe[0]--->(dup)--->stdin--->sort
#include <stdio.h> #include <unistd.h> #define oops(m,x) {perror(m);exit(x);} int main( int ac, char **av ) { int thepipe[2]; int newfd; int pid; if ( ac != 3 ){ fprintf(stderr, "usage:pipe cmd1 cmd2\n"); exit(1); } if ( pipe( thepipe ) == -1 ) oops("cannot get a pipe\n", 1); if ( ( pid = fork() ) == -1 ) oops("cannot fork", 2); if ( pid > 0 ){ close( thepipe[1]); if ( dup2(thepipe[0],0) == -1) oops("could not redirect stdin", 3); close(thepipe[0]); execlp(av[2], av[2], NULL); oops(av[2],4); } close(thepipe[0]); if ( dup2(thepipe[1],1) == -1 ) oops("could not redirect stdout",4); close(thepipe[1]); execlp(av[1], av[1], NULL); oops(av[1],5); return 0; }程序输出:
leichaojian@ThinkPad-T430i:~$ ./a.out who sort leichaojian :0 2014-09-02 20:42 (:0) leichaojian pts/0 2014-09-02 20:44 (:0)
对于各种函数的解释,极力推荐APUE
相关文章推荐
- unix/linux编程实践教程----I/O重定向和管道
- Unix/Linux编程实践教程三 编写Pwd
- Unix/Linux编程实践教程
- unix/linux编程实践教程------学习笔记
- unix/linux编程实践教程------学习笔记(五)
- Unix/Linux编程实践教程 笔记8 进程和程序:编写命令解释器sh
- unix/linux编程实践教程:进程和程序
- unix/linux编程实践教程:学习stty
- unix/linux编程实践教程----fflush函数有什么作用
- Unix/Linux编程实践教程
- 解读unix/linux编程实践教程------cp1.c延伸1
- Unix/Linux编程实践教程----cp1.c详解
- Unix & Linux大学教程(二):Shell、重定向和管道
- unix/linux编程实践教程:who命令
- Unix/Linux编程实践教程四 stty
- Unix/Linux编程实践教程参考答案-----第二章学习笔记
- unix/linux编程实践教程读后感(2)
- unix/linux编程实践教程------fcntl和ioctl
- unix/linux编程实践教程------学习笔记(三)
- unix/linux编程实践教程------execve, execlp, execvp, execle比较笔记