fcntl函数,可以改变已经打开文件的性质。
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fcntl(int filedes,int cmd,...);
返回:若成功则依赖于cmd,若出错则为-1
.用fcntl给文件加锁:
当多个用户共同使用、操作一个文件的时候,linux通常采用的方法是给文件上锁,来避免共享资源产生竞
争的状态. 文件锁包括建议锁和强制性锁。建议性锁要求上锁文件的进程都要检测是否有锁存在,并尊重已有
的锁。强制性锁由内核和系统执行的锁。
fcntl不仅可以实现建议性锁而且可以实施强制性锁。
>F_RDLCK---共享读锁
>F_WRLCK---独占性写锁
>F_UNLCK---解锁一个区域
要加锁或解锁的区域的起始地址,由l_start和l_whence两者决定。l_start是相对位移量(字节),l_whence则决定了
相对位移量的起点.
区域的长度由l_len表示
关于加锁和解锁区域的说明:
>该区域不能在文件起始位置之前
>若l_len为0,表示锁的区域从其起点开始直至最大可能位置为止,即文件数据都处于锁的范围
>通常用l_start说明为0,l_whence说明为SEEK_SET,l_len说明为0来锁整个文件
.ioctl函数:
ioctl函数是I/O操作的杂物箱,不能用其他函数表示的I/O操作通常都能用ioctl表示。终端I/O是ioctl的最
大使用方面,主要用于设备的I/O控制.
#include <unistd.h>
#include <sys/ioctl.h>
int ioctl(int filedes,int request,...);
返回:若出错则为-1,若成功则为其他值
.select实现I/O复用:
I/O处理的五种模型:
1>阻塞I/O模型:若所调用的I/O函数没有完成相关的功能就会是进程挂起,直到相关数据到达才会返回
如:终端、网络设备的访问
2>非阻塞模型:当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误
如:open,read,write等。
3>I/O多路转接模型:如果请求的I/O操作阻塞,且它不是真正阻塞I/O,而且让其中的一个函数等待,在这
期间,I/O还能进行其他操作。如:select函数。
4>信号驱动I/O模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,
从而启动I/O.
5>异步I/O模型:在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核,由内核进行
后续处理
对文件描述符的处理主要设计4个宏函数:
FD_ZERO(fd_set *set):清除一个文件描述符集
FD_SET(int fd,fd_set *set)将一个文件描述符加入文件描述符集中
FD_CLR(int fd,fd_set *set)将一个文件描述符从文件描述符集中清除
FD_ISSET(int fd,fd_set *set)测试该集中的一个给定位是否有变化
在使用select函数之前,首先用FD_ZERO和FD_SET初始化文件描述符集,并使用select时,可循环使用FD_ISSET测试
描述符集,执行完成对相关的文件描述符后,使用FD_CLR来清除描述符集.
Example: select.c
/*select.c*/
//每隔10秒从第一个文件中读取7个字节写入到第二个文件中
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
int main(void)
{
int fds[2];
char buf[7];
int i,rc,maxfd;
fd_set inset1,inset2;
struct timeval tv;
if((fds[0] = open ("hello1", O_RDWR|O_CREAT,0666))<0)
perror("open hello1");
if((fds[1] = open ("hello2", O_RDWR|O_CREAT,0666))<0)
perror("open hello2");
if((rc = write(fds[0],"Hello!\n",7)))
printf("rc=%d\n",rc);
lseek(fds[0],0,SEEK_SET);
maxfd = fds[0]>fds[1] ? fds[0] : fds[1];
FD_ZERO(&inset1);
FD_SET(fds[0],&inset1);
FD_ZERO(&inset2);
FD_SET(fds[1],&inset2);
tv.tv_sec=2;
tv.tv_usec=0;
while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2))
{
if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)
perror("select");
else
{
if(FD_ISSET(fds[0],&inset1))
{
rc = read(fds[0],buf,7);
if(rc>0)
{
buf[rc]='\0';
printf("read: %s\n",buf);
}
else
perror("read");
}
if(FD_ISSET(fds[1],&inset2))
{
rc = write(fds[1],buf,7);
if(rc>0)
{
buf[rc]='\0';
printf("rc=%d,write: %s\n",rc,buf);
}
else
perror("write");
sleep(10);
}
}
}
exit(0);
}