linux系统函数学习_(3)lseek函数、fcntl函数和dup/dup2函数
lseek()函数
头文件:
#include<sys/types.h>
#include<unistd.h>
功能:
获取文件大小,移动文件指针,文件拓展
即修改文件偏移量(读写位置))
函数原型:
off_t lseek(int fd, off_t offset, int whence);
参数:
- fd: 文件描述符
- offset: 文件指针的偏移量
- whence: 起始偏移位置
SEEK_SET -> 从文件头部向后偏移
SEEK_CUR -> 从当前位置向后偏移
SEEK_END -> 从文件尾部向后偏移
返回值:
成功:较起始位置的偏移量;失败: -1 errno
示例
// lseek.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int fd = open("a.txt", O_RDWR);
if(fd == -1)
{
perror("open file");
exit(1);
}
// 获取文件大小
int ret = lseek(fd, 0, SEEK_END);
printf("file length = %d\n", ret);
// 文件拓展
ret = lseek(fd, 2000, SEEK_END);
printf("return value %d\n", ret);
// 实现文件拓展,需要再最后做一次写操作
write(fd, "a", 1);
close(fd);
return 0;
}
使用 truncate 函数,可直接拓展文件。
int ret = truncate("dict.cp", 250);
示例2:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(void)
{
int fd, n;
char msg[] = "It's a test for lseek\n";
char ch;
fd = open("lseek.txt", O_RDWR|O_CREAT, 0644);
if(fd < 0){
perror("open lseek.txt error");
exit(1);
}
write(fd, msg, strlen(msg)); // 使用fd对打开的文件进行写操作,文件读写位置位于文件结尾处。
lseek(fd, 0, SEEK_SET); // 修改文件读写指针位置,位于文件开头。 注释该行会怎样呢?
while((n = read(fd, &ch, 1))){
if(n < 0){
perror("read error");
exit(1);
}
write(STDOUT_FILENO, &ch, n); // 将文件内容按字节读出,写出到屏幕
}
close(fd);
return 0;
}
fcntl()函数
根据文件描述符来操作文件的状态,改变已打开的文件属性-- #include<fcntl.h>
函数原型:
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock* lock);
- 复制一个现有的描述符 - - cmd: F_DUPFD
- 获得/设置文件描述符标记 - - cmd: F_GETFD、F_SETFD
- 获得设置文件状态标记 - - cmd: F_GETFL、 F_SETFL
- 获得/设置异步I/O所有权 - - cmd: F_GETOWN、F_SETOWN
- 获得/设置记录锁 - - cmd: F_GETLK、F_SETLK、F_SETLKW
示例
//fcntl.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd;
int flag;
// 测试字符串
char *p = "我们是一个有中国特色的社会主义国家!!!!!!";
char *q = "呵呵, 社会主义好哇。。。。。。";
// 只写的方式打开文件
fd = open("test.txt", O_WRONLY);
if(fd == -1)
{
perror("open");
exit(1);
}
// 输入新的内容,该部分会覆盖原来旧的内容,从文件的起始位置开始写
if(write(fd, p, strlen(p)) == -1)
{
perror("write");
exit(1);
}
// 使用 F_GETFL 命令得到文件状态标志
flag = fcntl(fd, F_GETFL, 0);
if(flag == -1)
{
perror("fcntl");
exit(1);
}
// 将文件状态标志添加 ”追加写“ 选项
flag |= O_APPEND;
// 将文件状态修改为追加写
if(fcntl(fd, F_SETFL, flag) == -1)
{
perror("fcntl -- append write");
exit(1);
}
// 再次输入新内容,该内容会追加到旧内容的后面,从文件的末尾位置开始写
if(write(fd, q, strlen(q)) == -1)
{
perror("write again");
exit(1);
}
// 关闭文件
close(fd);
return 0;
}
dup()函数
复制现有的文件描述符(重定向)
int dup(int oldfd);
返回的是文件描述符中没有被占用的最小的文件描述符
示例
// dup.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("a.txt", O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
printf("file open fd = %d\n", fd);
// 找到进程文件描述表中 ==第一个== 可用的文件描述符
// 将参数指定的文件复制到该描述符后,返回这个描述符
int ret = dup(fd);
if(ret == -1)
{
perror("dup");
exit(1);
}
printf("dup fd = %d\n", ret);
char* buf = "你是猴子派来的救兵吗????\n";
char* buf1 = "你大爷的,我是程序猿!!!\n";
write(fd, buf, strlen(buf));
write(ret, buf1, strlen(buf1));
close(fd);
return 0;
}
dup2()函数
int dup2(int oldfd, int newfd);
如果newfd是一个被打开的文件描述符,在拷贝前先关掉newfd所指定的文件
oldfd和newfd是同一个文件描述符时,newfd打开时不用关闭。
示例
// dup2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("english.txt", O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
int fd1 = open("a.txt", O_RDWR);
if(fd1 == -1)
{
perror("open");
exit(1);
}
printf("fd = %d\n", fd);
printf("fd1 = %d\n", fd1);
int ret = dup2(fd1, fd);
if(ret == -1)
{
perror("dup2");
exit(1);
}
printf("current fd = %d\n", ret);
char* buf = "主要看气质 ^_^!!!!!!!!!!\n";
write(fd, buf, strlen(buf));
write(fd1, "hello, world!", 13);
close(fd);
close(fd1);
return 0;
}
参考
- 参考黑马程序员linux系统编程资料
- fcntl函数的用法总结