上代码:
/* upper.c */ #include <stdio.h> int main(void) { int ch; while((ch = getchar()) != EOF) { putchar(toupper(ch)); } return 0; }
终端输入:
upper的默认输出是终端,
gcc -g upper.c -o upper
./upper
便可以任意输入,以ctr c退出
文件管道输入;
touch file.txt
可以对file.txt输入任意字符串
终端输入./upper < file.txt
这是把file.txt通过管道作为输入端
STDIN_FILENO绑定:
STDIN_FILENO是一个打开文件句柄,对应的函数主要包插open/read/write/close等系统调用.
操作系统提共的API都是以文件描述符来表示文件(具体可学习ext2文件系统&&VFS),STDIN_FILENO就是标准输入设备,一般是键盘文件描述符,因为我们可以通过dup2将STDIN_FILENO绑定到新打开的文件描述符,实现自动化.
可再写一个包装器,
/*wrapper.c*/
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> int main(int argc,char* argv[]) { int fd; if(argc != 2)//参数是否正确 { printf("please input the file path"); exit(1); } fd = open(argv[1],O_RDONLY);//以read only方式打开文件 if(fd < 0)//文件是否打开正确 { printf("open file err"); exit(1); } dup2(fd,STDIN_FILENO);//dup2复制文件描述符 close(fd);//关闭fd execl("./upper","upper",NULL);//execl执行,最后一个参数记得写NULL perror("exec ./upper"); exit(1);//退出. }
程序比较简单,但我们可以不断扩展,比如之前学习了fork,我们可以试想想能不能让子进程去打开并执行,
代码如下.
/*wrapper.c*/ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> int main(int argc,char* argv[]) { int fd,pid; if(argc != 2) { printf("please input the file path"); exit(1); } pid = fork(); if(pid < 0) { printf("fork failed"); }else if(pid == 0) { fd = open(argv[1],O_RDONLY); if(fd < 0) { printf("open file err"); exit(1); } dup2(fd,STDIN_FILENO); close(fd); execl("./upper","upper",NULL); perror("exec ./upper"); }else { //do nothing } exit(1); }