linux入门到精通-第九章-文件操作(2)

发布时间:2024年01月08日

参考

视频教程

文件描述符复制

概述

dup() 和 dup2() 是两个非常有用的系统调用,都用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。

这个过程类似于现实生活中的配钥匙,钥匙相当文件描述符,锁相当于文件,本来一个钥匙开一把锁,相当于,通过旧的钥匙复制了一把新的钥匙,这样的话,旧的钥匙和新的钥匙都能开启这把锁。

对比于 dup(),dup2() 也一样,通过原来的文件描术符复制出一个新的文件描述符,这样的话,原来的文件描述符和新的文件描述符都指向同一个文件,我们操作两个文件描述符的任何一个,都能操作它所对应的文件.。

dup函数

#include <unistd.h>
int dup(int oldfd) ;
功能:
	通过 o1dfd 复制出一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终 o1dfd 和新的文件描述符都指向同一个文件。
参数:
	o1dfd :需要复制的文件描述符 o1dfd
返回值:
	成功: 新文件描述符
	失败:-1

dup2函数

#include <unistd.h>
int dup2(int oldfd, int newfd);
功能:
	通过 o1dfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终o1dfd 和新的文件描述符 newfd 都指向同一个文件
参数:
	o1dfd :需要复制的文件描述符
	newfd :新的文件描述符,这个描述符可以人为指定一个合法数字(0  1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭 c1ose()断开这个数字和某个文件的关联,再来使用这个合法数字
返回值:
	成功:返回 newfd
	失败: 返回 -1

代码测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//dup dup2
int main(void)
{
    int fd = -1;
    int newfd = -1;
    //1.打开文件
    fd = open("test.txt",O_RDWR | O_CREAT,0644);
    if (-1 == fd)
    {
        perror("open");
        return 1;
    }
    printf("fd = %d\n",fd);
    //文件描述符复制
    // newfd = dup(fd);
    newfd = 2;
    // 如果文件描述符2已经跟某个文件关联,那么就先解除与该文件的关联,然后将该文件描述符与fd关联同一个文件
    newfd = dup2(fd, newfd);
    if (-1 == newfd)
    {
        perror("dup");
        return 1;
    }
    printf("newfd = %d\n",newfd);

    //2.操作
    write(fd,"ABCDEFG",7);
    write(newfd,"1234567",7);

    //3,关闭文件描述符
    close(fd);
    close(newfd);
}

fcnlt函数

介绍

查看帮助文档

man fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd,int cmd, .../* arg */);
功能:改变已打开的文件性质,fcntl针对描述符提供控制。
参数
	fd; 操作的文件描述符
	cmd: 操作方式
	arg: 针对cmd的值,fcntl能够接受第三个参数int arg。
返回值:
	成功:返回某个其他值
	失败:-1

fcntl函数有5种功能

  • 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_GETLKF,F_SETLK或F、SETLKW)

文件描述符复制类似dup

//2,文件描述符复制
//功能等价于dup函数
//第三个参数0 表示返回一个最小的可用的文件描述符,并且大于或者等于0
newfd = fcntl(fd, F_DUPFD, 0);
if (-1 == newfd)
{
	perror("fcntl");
	return 1;
}

设置和获取文件标记

在原有状态行添加O_APPEND追加标记

//2,获取文件状态标记
    int ret = fcntl(fd,F_GETFL);
    if (-1 == ret)
    {
        perror("fcnti");
        return 1;
    }
    if(ret & O_APPEND)
    {
        printf("before append\n");
    }
    else
    {
        printf("before not append\n");
    }
    //3,设置文件状态标记
    ret = ret | O_APPEND ;
    ret = fcnlt(fd,F_SETFL, ret);
    if (-1 == ret)
    {
        perror("fcnti");
        return 1;
    }

目录操作相关函数

getcwd函数

#include <unistd.h>
char *getcwd(char *buf,size t size);
功能:获取当前进程的工作目录
参数:
	buf : 缓冲区,存储当前的工作目录
	size : 缓冲区大小
返回值:
	成功: buf中保存当前进程工作目录位置
	失败: NULL

chdir函数

#include <unistd.h>
int chdir(const char *path);
功能: 修改当前进程(应用程序)的路径
参数
	path: 切换的路径
返回值:
	成功:0
	失败:-1

注意,即使可以修改,但是用pwd打印,路径还是原来,没有改变

测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define SIZE 32
//getcwd chdir
int main(void)
{
	int ret = -1;
	char buf[SIZE];
	//1,获取当前进程的工作目录
	memset(buf, 0, SIZE);
	if (NULL == getcwd(buf, SIZE))
	{
		perror("getcwd");
		return 1;
	}
	printf("buf:%s\n", buf);
	//2,改变当前进程的工作目录
	ret = chdir("/home/deng");
	if (-1 == ret)
	{
		perror("chdir");
		return 1;
	}
	//3,获取当前进程的工作目录
	memset(buf, 0, SIZE);
	if (NULL == getcwd(buf,SIZE))
	{
		printf("buf:%s\n", buf);
	}
}

opendir函数

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:
	name: 目录名
返回值:
	成功:返回指向该目录结构体指针
	失败: NULL

closedir函数

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭目录
参数:
	dirp: opendir返回的指针
返回值:
	成功: 0
	失败: -1

测试代码

#include <stdio.h>
#include <string.h>
#include <stdlib,h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
//目录打开和关闭
int main(void)
{
	DIR *dir = NULL;
	//1,打开目录
	dir = opendir("test");
	if (NULL == dir)
	{
		perror("opendir");
		return 1;
	}
	printf("打开目录成功...,\n");
	//2,关闭目录
	closedir(dir);
	return 0;
}

readdir函数

#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取目录
参数:
	dirp: opendir的返回值
返回值:
	成功:目录结构体指针
	失败: NULL

结构体说明:

struct dirent
{
	ino_t d_ino; // 此目录进入点的inode
	off_t d_off; // 目录文件开头至此目录进入点的位移
	signed short int d_reclen; // d_name 的长度,不包含NULL 字符
	unsigned char d_type; // d_type 所指的文件类型
	char d_name[256]; // 文件名
}

d_type文件类型说明:

取值含义
DT_BLK块设备
DT_CHR字符设备
DT_DIR目录
DT_LNK软链接
DT_FIFO管道
DT_REG普通文件
DT_SOCK套接字
DT_UNKNOWN未知

代码测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>

int main()
{
    //目录打开和关闭
    DIR *dir = NULL;
    struct dirent *d = NULL;
    //1,打开目录
    dir = opendir("/usr/local/cpp_demo");
    if (NULL == dir)
    {
        perror("opendir");
        return 1;
    }

    printf("打开目录成功.... \n");
    //2。循环读取目录内密
    while(1)
    {
        //读取目录的内容
        d = readdir(dir);
        if (NULL == d)
        {
            perror("readdir");
            break;
        }
        printf(" d name:%s , type: ",d->d_name);
        //判断文件类型
        switch(d->d_type)
        {
            case DT_BLK:
                printf("央设备");
                break;
            case DT_CHR:
                printf("字符设备");
                break;
            case DT_DIR:
                printf("目录");
                break;
            case DT_FIFO:
                printf("管道");
                break;
            case DT_LNK :
                printf("符号链接");
                break;
            case DT_REG:
                printf("普通文件");
                break;
            case DT_SOCK:
                printf("套接字");
                break;
            default:
                printf("未知文件类型");
        }
        printf("\n");
    }
    

    //3,关闭目录
    closedir(dir);
}

文章来源:https://blog.csdn.net/Blueeyedboy521/article/details/131073724
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。