1、fcntl函数—改变已经打开文件的属性
函数原型:
该函数有五种功能:
(1)复制一个现有的描述符(cmd=F_DUPFD),新的文件描述符作为函数的返回值。
(2) 获得/设置文件描述符标记(cmd=FGETFD 或 FSETFD). (3)获得/设置文件状态标记(cmd=FGETFL 或 FSETFL). (4)获得/设置异步I/O所有权(cmd=FGETOWN 或 (FSETOWN).
(5)获得/设置记录锁(cmd=FGETLK,FSETLK或F_SETLKW)
返回值:若成功,依赖于传入的cmd;若出错,则返回-1
2、重定向函数dup和dup2
函数原型:
函数说明:
(1)由dup返回的新文件描述符一定是当前可用文件描述符中的最小值
(2)对于dup2,可用newfd参数指定新描述符的值,如果newfd已经打开,则先将其关闭,若newfd等于oldfd,则dup2返回newfd,而不关闭它。
(3)返回值:对于这两个函数,若成功,返回新的文件描述符,若出错,返回-1
3、轮询方式读取标准输入
基于fcntl函数,我们可以实现SetNoBlock函数,将文件描述符设置为非阻塞:
函数具体实现过程如下:
1 #include<stdio.h>2 #include<unistd.h>3 #include<fcntl.h>4 5 void SetNoBlock(int fd)6 {7 int f1=fcntl(fd,F_GETFL);8 if(f1<0)9 {10 perror("fcntl");11 return ;12 }13 fcntl(fd,F_SETFL,f1|O_NONBLOCK);14 }
15 //使用F_GETFL将当前的文件描述符的属性取出来(这是一个位图). 然后再使 用FSETFL将文件描述符设置回去设置回去的同时 , 加上一个 ONONBLOCK参数.16 int main()17 {18 SetNoBlock(0);19 while(1)20 {21 char buf[1024]={0};22 ssize_t s=read(0,buf,sizeof(buf)-1);23 if(s<0)24 {25 perror("read");26 sleep(1);27 continue;28 }29 printf("input:%s\n",buf);30 }31 return 0;32 }
运行结果:
该进程,没有等待写就返回了,是非阻塞的。
4、使用dup将标准输出重定向到文件中
具体代码:
1 #include<stdio.h>2 #include<unistd.h>3 #include<fcntl.h>4 5 int main()6 {7 int fd=open("./log",O_CREAT|O_RDWR);8 if(fd<0)9 {10 perror("open");11 return 1;12 }13 close(1);14 int newFd=dup(fd);15 if(newFd!=1)16 {17 perror("dup");18 return 1;19 }20 printf("newFd:%d\n",newFd);21 close(fd);22 23 for(;;)24 {25 char buf[1024]={0};26 ssize_t s=read(0,buf,sizeof(buf)-1);27 if(s<0)28 {29 perror("read");30 continue;31 }32 printf("%s",buf);33 fflush(stdout);34 }35 close(newFd);36 return 0;37 }
运行结果:
写入数据
打开./log文件,查看刚刚写入的文件:
5、用dup2将标准输出重定向到文件中
具体代码:
1 #include<stdio.h>2 #include<unistd.h>3 #include<fcntl.h>4 5 int main()6 {7 int fd=open("./log",O_CREAT|O_RDWR);8 if(fd<0)9 {10 perror("open");11 return 1;12 }13 close(1);14 dup2(fd,1);15 for(;;)16 {17 char buf[1024]={0};18 ssize_t s=read(0,buf,sizeof(buf)-1);19 if(s<0)20 {21 perror("read");22 break;23 }24 printf("%s",buf);25 fflush(stdout);26 }27 return 0;28 }
运行结果:
打开文件./log我们可以看到,将输入的数据输出到了该文件中。