fcntl系统调用
例1: 文件的状态标志
myfcntl_access.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#define ERROR(flag) \
if(flag) \
{ \
printf("%d: ",__LINE__); \
fflush(stdout); \
perror("error"); \
exit(errno); \
}
int main(int argc,char *argv[])
{
int ret;
int access_mode;
int fd;
fd = open(argv[1], O_RDWR );
ERROR(fd == -1);
ret = fcntl(fd, F_SETFL, O_APPEND | O_NONBLOCK);
ERROR(ret < 0);
ret = fcntl(fd, F_GETFL,0);
ERROR(ret < 0);
access_mode = ret & O_ACCMODE;
if (access_mode == O_RDONLY)
{
printf("%s: read only",argv[1]);
}
else if (access_mode == O_WRONLY)
{
printf("%s: write only",argv[1]);
}
else if (access_mode == O_RDWR)
{
printf("%s: read + write",argv[1]);
}
if (ret & O_APPEND)
{
printf(", append");
}
if (ret & O_NONBLOCK)
{
printf(", nonblock");
}
printf("\n");
return 0;
}
编译链接执行, 结果输出文件的属性如下:
例2: 对文件描述符设置读写锁
myfcntl_lock.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define ERROR(flag) \
if(flag) \
{ \
printf("%d: ",__LINE__); \
fflush(stdout); \
perror("error"); \
exit(errno); \
}
int lock_set(int fd, struct flock * lock)
{
if (fcntl(fd, F_SETLK, lock) == 0)
{
if (lock->l_type == F_RDLCK)
{
printf("set read lock, pid:%d\n", getpid());
}
else if (lock->l_type == F_WRLCK)
{
printf("set write lock, pid:%d\n", getpid());
}
else if (lock->l_type == F_UNLCK)
{
printf("release lock, pid:%d\n", getpid());
}
}
else
{
perror("lock operation fail\n");
return -1;
}
return 0;
}
int lock_test(int fd, struct flock * lock)
{
if (fcntl(fd, F_GETLK, lock) == 0)
{
if (lock->l_type == F_UNLCK)
{
printf("lock can be set in fd\n");
return 0;
}
else
{
if (lock->l_type == F_RDLCK)
{
printf("can't set lock, read lock has been set by: %d\n",
lock->l_pid);
}
else if (lock->l_type == F_WRLCK)
{
printf("can't set lock, write lock has been set by: %d\n",
lock->l_pid);
}
return -2;
}
}
else
{
perror("get incompatible locks fail");
return -1;
}
}
int main(int argc,char *argv[1])
{
int fd;
int ret;
struct flock lock;
char read_buf[32];
fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
ERROR(fd == -1);
ret = write(fd, "=====hello 123456789=====", 25);
ERROR(ret != 25);
memset(&lock, 0, sizeof (struct flock));
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = F_RDLCK;
if (lock_test(fd, &lock) == 0)
{
lock.l_type = F_RDLCK;
lock_set(fd, &lock);
}
lseek(fd, 0, SEEK_SET);
ret = read(fd, read_buf, 25);
ERROR(ret < 0);
read_buf[ret] = '\0';
printf("%s\n", read_buf);
getchar();
lock.l_type = F_WRLCK;
if (lock_test(fd, &lock) == 0)
{
lock.l_type = F_WRLCK;
lock_set(fd, &lock);
}
getchar();
lock.l_type = F_UNLCK;
lock_set(fd, &lock);
close(fd);
return 0;
}
编译链接运行, 有如下输出结果:
结果1: 只在一个终端执行, 对打开文件的描述符加读锁, 写锁及解锁结果如下图:
结果2: 两个终端同时执行同样的命令, 再先后按回车键, 对打开的文件描述符加读锁,写锁及解锁, 输出结果如下:
理解如下:
1. 此文件读写锁没有强制性(提供机制, 由接口使用者实现策略).
2. 不同进程对同一打开的文件描述符可以同时加读锁
3. 对已加读锁的文件描述符, 不能再加写锁
结果3: 两个终端同时执行同样的命令, 其中一个先连续按两次回车, 使其对文件描述符加写锁, 如下:
理解如下:
对已加写锁的文件,不能加读锁, 也不能加写锁