linux下文件函数,Linux下编程-文件与IO(3) 文件共享和fcntl函数

Linux下编程------文件与IO(三) 文件共享和fcntl函数

文件共享

072925223

一个进程打开了两个文件

文件表条目(file-table-entry):

1.文件状态标志(file-status-flags): 读/写/追加/同步/非阻塞等;

2.当前文件偏移量

3.v节点指针

[cpp] view

plaincopy

072925224.png

072925225.svg

//验证

intmain(intargc,char*argv[])

{

intfd1 = open("test.txt", O_RDONLY);

if(fd1 == -1)

err_exit("fd1 open O_RDONLY error");

intfd2 = open("test.txt", O_RDWR);

if(fd2 == -1)

err_exit("fd2 open O_RDWR error");

//读取fd1

charbuf[BUFSIZ];

if(read(fd1, buf, 10) == -1)

err_exit("read fd1 error");

cout <

//读取fd2

bzero(buf, 10);

if(read(fd2, buf, 10) == -1)

err_exit("read fd1 error");

cout <

lseek(fd1, 0, SEEK_SET);

lseek(fd2, 0, SEEK_SET);

write(fd2, "Helloworld", 10);

bzero(buf, 10);

if(read(fd1, buf, 10) == -1)

err_exit("read fd1 error");

cout <

}

一个进程多次打开同一个文件,文件指针是互不干扰的,因为他们各自维护自己文件表(数据结构),但是如果修改了文件的内容,那么v结点信息改变,则都会受到影响。

072925226

两个独立的进程打开同一个文件

复制文件描述符

072925227

方法有三种:

1.dup

2.dup2

其中dup2相当于先close在执行dup。

[cpp] view

plaincopy

072925224.png

072925225.svg

#include 

intdup(intoldfd);

intdup2(intoldfd,intnewfd);

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例

intmain(intargc,char*argv[])

{

intfd = open("text.txt", O_WRONLY|O_TRUNC);

if(fd == -1)

err_exit("open O_WRONLY error");

//    close(1);   //将标准输出关闭, 则文件描述符1将空闲

//    int dupfd = dup(fd);

intdupfd = dup2(fd, 1);

cout <

}

[cpp] view

plaincopy

072925224.png

072925225.svg

/** 示例: 实现文件拷贝

其中execlp会在后面介绍

**/

intmain(intargc,char*argv[])

{

if(argc 

err_quit("usage: ./main file-name1 file-name2");

close(STDIN_FILENO);

open(argv[1], O_RDONLY);

close(STDOUT_FILENO);

open(argv[2], O_WRONLY|O_CREAT, 0666);

execlp("/bin/cat","cat", NULL);

err_exit("execlp error");

}

3.fcntl

[cpp] view

plaincopy

072925224.png

072925225.svg

intfcntl(intfd, F_DUPFD, .../* arg */);

//示例见下

fcntl

[cpp] view

plaincopy

072925224.png

072925225.svg

#include 

#include 

intfcntl(intfd,intcmd, .../* arg */);

操纵文件描述符, 改变已经打开的文件的属性

fcntl常用操作(cmd常用取值)

F_DUPFD (long)

复制文件描述符

F_GETFD (void)

F_SETFD (long)

文件描述符标志

F_GETFL (void)

F_SETFL (long)

文件状态标志

F_GETLK

F_SETLK,F_SETLKW(阻塞)

文件锁

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例: 复制文件描述符

intmain(intargc,char*argv[])

{

intfd = open("text.txt", O_WRONLY|O_TRUNC);

if(fd == -1)

err_exit("open O_WRONLY error");

close(1);   //将标准输出关闭, 则文件描述符1将空闲

// 当cmd使用F_DUPFD时, 第三个参数代表搜索的起始位置

intdupfd = fcntl(fd, F_DUPFD, 1);// 1代表: 从1开始搜索一个空闲的文件描述符

if(dupfd 

err_exit("fcntl F_DUPFD error");

cout <

}

文件状态标志

F_GETFL(void)

Get the file access mode and the file status flags; arg is ignored.

F_SETFL(int)

Set the file status flags to  the  value  specified  by  arg.   File  access  mode(O_RDONLY,  O_WRONLY,  O_RDWR)  and  file  creation  flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored.  On Linux this command can change only  the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags.

设置文件状态的时候,注意要先使用F_GETFL获取,否则原来的状态会丢失。

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例: 给文件描述符0设置成非阻塞模式

intmain(intargc,char*argv[])

{

intflags = fcntl(0, F_GETFL, 0);

if(flags == -1)

err_exit("fcntl get error");

flags |= O_NONBLOCK;

if(fcntl(0, F_SETFL, flags) == -1)

err_exit("fcntl set error");

charbuf[BUFSIZ];

if(read(0, buf,sizeof(buf)) == -1)

err_exit("read STDIN_FILENO error");

cout <

cout <

}

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例: 文件状态设置与清除(函数封装)

voidset_fl(intfd,intsetFlag)

{

intflags = fcntl(fd, F_GETFL, 0);

if(flags == -1)

err_exit("fcntl get flags error");

//设置状态

flags |= setFlag;

if(fcntl(fd, F_SETFL, flags) == -1)

err_exit("fcntl set flags error");

}

voidclr_fl(intfd,intclrFlag)

{

intflags = fcntl(fd, F_GETFL, 0);

if(flags == -1)

err_exit("fcntl get flags error");

//清除状态

flags &= ~clrFlag;

if(fcntl(fd, F_SETFL, flags) == -1)

err_exit("fcntl set flags error");

}

//测试

intmain(intargc,char*argv[])

{

set_fl(0, O_NONBLOCK);

clr_fl(0, O_NONBLOCK);

charbuf[BUFSIZ];

if(read(0, buf,sizeof(buf)) == -1)

err_exit("read STDIN_FILENO error");

cout <

cout <

}

文件锁

F_SETLK(struct flock *)

Acquire  a lock (when l_type is F_RDLCK or F_WRLCK) or release a lock (when l_type is F_UNLCK) on the bytes specified by the l_whence, l_start, and l_len  fields  of lock.   If a conflicting lock is held by another process, this call returns -1 and sets errno to EACCES or EAGAIN.

F_SETLKW(struct flock *) 如果加锁不成功:会一直阻塞直到解锁

As for F_SETLK, but if a conflicting lock is held on the file, then wait for  that lock to be released.  If a signal is caught while waiting, then the call is interrupted and (after the signal  handler  has  returned)  returns  immediately  (with return value -1 and errno set to EINTR; see signal(7)).

F_GETLK(struct flock *)

On  input  to this call, lock describes a lock we would like to place on the file.

If the lock could be placed, fcntl() does  not  actually  place  it,  but  returns F_UNLCK  in  the l_type field of lock and leaves the other fields of the structure unchanged.  If one or more  incompatible  locks  would  prevent  this  lock  being placed,  then  fcntl()  returns  details  about  one of these locks in the l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the  PID  of  the process holding that lock.

[cpp] view

plaincopy

072925224.png

072925225.svg

//文件锁结构体

structflock

{

...

shortl_type;/* Type of lock: F_RDLCK,

F_WRLCK, F_UNLCK */

shortl_whence;/* How to interpret l_start:

SEEK_SET, SEEK_CUR, SEEK_END */

off_t l_start;   /* Starting offset for lock */

off_t l_len;     /* Number of bytes to lock */

pid_t l_pid;     /* PID of process blocking our lock

(F_GETLK only) */

...

};

注意: Specifying 0 for l_len has the special meaning: lock all bytes starting  at

the  location  specified  by l_whence and l_start through to the end of file,

no matter how large the file grows.

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例1

intmain(intargc,char*argv[])

{

intfd = open("test.txt", O_RDWR|O_CREAT|O_TRUNC, 0666);

if(fd == -1)

err_exit("open file error");

structflock lock;

lock.l_type = F_WRLCK;  //设定独占锁

lock.l_whence = SEEK_SET;

lock.l_start = 0;

lock.l_len = 0; //锁定全部文件

//if (fcntl(fd, F_SETLK, &lock) == 0)   //对比下面

if(fcntl(fd, F_SETLKW, &lock) == 0)

{

cout <

cin.get();

lock.l_type = F_UNLCK;

lock.l_whence = SEEK_SET;

lock.l_start = 0;

lock.l_len = 0;

if(fcntl(fd, F_SETLK, &lock) == -1)

err_exit("file unlock error");

else

cout <

}

else

err_exit("file lock error");

}

[cpp] view

plaincopy

072925224.png

072925225.svg

//示例2: 打印加锁进程号

intmain(intargc,char*argv[])

{

intfd = open("test.txt", O_RDWR|O_CREAT|O_TRUNC, 0666);

if(fd == -1)

err_exit("open file error");

structflock lock;

lock.l_type = F_WRLCK;  //设定独占锁

lock.l_whence = SEEK_SET;

lock.l_start = 0;

lock.l_len = 0; //锁定全部文件

if(fcntl(fd, F_SETLK, &lock) == 0)

{

cout <

cin.get();

lock.l_type = F_UNLCK;

lock.l_whence = SEEK_SET;

lock.l_start = 0;

lock.l_len = 0;

if(fcntl(fd, F_SETLK, &lock) == -1)

err_exit("file unlock error");

else

cout <

}

else//如果失败, 则获取锁信息

{

if(fcntl(fd, F_GETLK, &lock) == -1)

err_exit("get lock error");

cout <

if(lock.l_type == F_WRLCK)

cout <

else

cout <

if(lock.l_whence == SEEK_SET)

cout <

elseif(lock.l_whence == SEEK_END)

cout <

else

cout <

}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。2楼u010850027昨天 16:53感谢小伙伴的分享,学习了`(*∩_∩*)′1楼XscKernel前天 16:41博文不错,我要转走啦~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值