linux系统函数学习_(3)lseek函数、fcntl函数和dup/dup2函数

linux系统函数学习_(3)lseek函数、fcntl函数和dup/dup2函数

lseek()函数

头文件:
#include<sys/types.h>
#include<unistd.h>
功能:
获取文件大小,移动文件指针,文件拓展
即修改文件偏移量(读写位置))

函数原型:

off_t lseek(int fd, off_t offset, int whence);

参数:

  1. fd: 文件描述符
  2. offset: 文件指针的偏移量
  3. 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);
  1. 复制一个现有的描述符 - - cmd: F_DUPFD
  2. 获得/设置文件描述符标记 - - cmd: F_GETFD、F_SETFD
  3. 获得设置文件状态标记 - - cmd: F_GETFL、 F_SETFL
  4. 获得/设置异步I/O所有权 - - cmd: F_GETOWN、F_SETOWN
  5. 获得/设置记录锁 - - cmd: F_GETLK、F_SETLK、F_SETLKW
fcntl
复制一个现有的描述符_cmd:
F_DUPFD
获得/设置文件描述符标记_cmd:
F_GETFD
F_SETFD
获得/设置文件状态标记_cmd:
F_GETFL
只读打开O_RDONLY
只写打开O_WRONLY
读写打开O_RDWR
执行打开O_EXEC
搜索目录打开O_SEARCH
追加写O_APPEND
非阻塞模式O_NONBLOCK
F_SETFL可更改的几个标识
O_APPEND
O_NONBLOCK
获得/设置异步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;
}

参考

  1. 参考黑马程序员linux系统编程资料
  2. fcntl函数的用法总结
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值