第六节 低级文件编程库

来源:互联网 发布:如何屏蔽淘宝推广广告 编辑:程序博客网 时间:2024/06/05 10:24

低级文件编程库常常用于方位终端、管道、设备和套接字等特殊文件,一般不用于普通磁盘文件,这是标准文件编程库的特长。

低级文件编程库听起来似乎很低级,其实它是UNIX中的I/O系统调用。它使用文件描述符,直接读写各类文件。低级文件编程库在输入输出上只有块读写的功能。

 

文件锁

多用户多任务操作系统非常重要的一个内容就是文件锁。用户在更新文件时,期望可以使用某种机制,防止两个进程同时更新文件同一区域的内容巍峨造成写丢失,或者防止文件内容在未更新完毕时被读取等并发引起的问题,这种机制就是文件锁。

进程在操作文件期间,可以使用文件所,锁定文件中的敏感信息,防止其它的进程操作该部分信息。函数fcntl提供了对文件任意区域设置锁的能力,既可以锁住全部文件,又可以锁住文件的部分记录,股文件锁由称为“记录锁”。

根据文件锁的访问方式,可以区分为读锁和写锁两种。文件记录在同一时刻,可以设置多个读锁,但仅仅能设置一个写锁,并且读写锁不能同时存在。

当函数fcntl专用于锁操作时,其原型为:

int fcntl(int fileds, int cmd, struct flock *arg);

其中,结构flock用于描述文件锁的信息,定义在头文件"fcntl.h"中,如下所示:

strct flock

{

short l_type; //锁类型,取值为F_RDLCk, F_WRLCK 或者 F_UNLCK 之一

short l_whence;//锁区域开始地址的相对位置,取值为SEEK_SET, SEEK_CUR 或者 SEEK_END 之一

off_t  l_start;//锁区域的开始地址偏移量

off_t  l_len;//锁区域的长度, 0 表示锁至文件末

off_t  l_pid;//拥有锁的进程ID号

};

 

函数fcntl在专用于锁操作时,参数cmd有三种取值:

(a) F_GETLK.获取文件描述符fileds对应文件制定区域的文件锁信息。

(b) F_SETLK.在文件描述符fileds 对应的文件的制定区域设置锁信息。

(C) F-SETLKW.该命令是F_SETLK命令的阻塞版本。

文件锁最典型应用于两方面:一是锁定文件中的临界数据,比如并发投票时文件记录的投票数; 二是利用具有互斥性质的写锁,实现进程的并发控制。

 

在锁机制的使用中,最常见的操作有锁的请求、释放、测试等;

(a) 测试锁。设计函数SeeLock,查询文件描述符fd对应文件的锁信息。

void SeeLock(int fd, int start, int len)

{

struct flock arg;

arg.l_type = F_WRLCK;

arg.l_whence = SEEK_SET;

arg.l_start = start;

arg.l_len = len;

 

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

{

fprintf(stderr, "See Lock failed./n");

}

else if(arg.l_type == F_UNLCK)

{

fprintf(stderr, "No Lock From %d to %d /n", start, start+len);

}

else if(arg.l_type == F_WRLCK)

{

fprintf(stderr, "Write Lock From %d to %d, id = %d/n", start, start+len, arg.l_pid);

}

else if(arg.l_type == F_WRLCK)

{

fprintf(stderr, "Read Lock From %d to %d, id = %d/n", start, start+len, arg.l_pid);

}

}

 

(b) 申请读锁。 以阻塞方式设计共享读锁申请函数GetReadLock。

 

void GetReadLock(int fd, int start, int len)

{ // 以阻塞方式在描述符fd对应文件中从start处的len字节上申请共享读锁

struct flock arg;

arg.l_type = F_RDLCK;

arg.l_whence = SEEK_SET;

arg.l_start = start;

arg.l_len = len;

if(fcntl(fd, F_SETLKW, &arg) == -1)

fprintf(stderr, "[%d] See Read Lock failed./n", getpid());

else

fprintf(stderr, "[%d] Set Read Lock From %d to %d/n", getpid(), start, start+len);

}

 

(c) 申请写锁. 以阻塞方式设计互斥写锁申请函数GetWrtieLock.

void GetWriteLock(int fd, int start, int len)

{ // 以阻塞方式在描述符fd对应文件中从start处的len字节上申请互斥写锁

struct flock arg;

arg.l_type = F_WRLCK;

arg.l_whence = SEEK_SET;

arg.l_start = start;

arg.l_len = len;

if(fcntl(fd, F_SETLKW, &arg) == -1)

fprintf(stderr, "[%d] See Write Lock failed./n", getpid());

else

fprintf(stderr, "[%d] Set Write Lock From %d to %d/n", getpid(), start, start+len);

}

 

(d) 释放锁. 设计文件锁释放函数ReleaseLock.

void ReleaseLock(int fd, int start, int len)

{ // 在描述符fd对应文件中释放从start处的len字节上的锁

struct flock arg;

arg.l_type = F_UNLCK;

arg.l_whence = SEEK_SET;

arg.l_start = start;

arg.l_len = len;

if(fcntl(fd, F_SETLKW, &arg) == -1)

fprintf(stderr, "[%d] UnLock failed./n", getpid());

else

fprintf(stderr, "[%d] UnLock From %d to %d/n", getpid(), start, start+len);

}

原创粉丝点击