Linux--文件操作

Linux的文件结构

在这里插入图片描述
root:该目录为系统管理员(也称作超级管理员)的用户主目录。

bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令。

boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。

dev:dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。

etc:所有的配置文件, 所有的系统管理所需要的配置文件和子目录都存放在这里。

home:用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。

var:存放着在不断变化的文件数据,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。

lib:这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

usr:系统用户工具和程序
– bin:用户命令
– sbin:超级用户使用的比较高级的管理程序和系统守护程序。
– include:标准头文件
– lib:库文件
– src:内核源代码

tmp:用来存放一些临时文件。

media:linux 系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别 的设备挂载到这个目录下。

mnt:临时挂载其他文件。

proc: 包含了进程的相关信息。

文件的操作方式

0) 文件描述符 fd
file descriptor

是一个>=0的整数
每打开一个文件,就创建一个文件描述符,通过文件描述符来操作文件

预定义的文件描述符:
0:标准输入,对应于已打开的标准输入设备(键盘)
1:标准输出,对应于已打开的标准输出设备(控制台)比如:cout
2: 标准错误, 对应于已打开的标准错误输出设备(控制台)比如:cerr

多次打开同一个文件,可得到多个不同的文件描述符。

1)使用底层文件操作(系统调用)
比如:read
可使用man 2 查看
2)使用I/O库函数
比如:fread
可使用man 3 查看

底层文件操作

write

(1) 用法
man 2 write
描述:向文件描述符中写数据

#include <unistd.h>   //头文件

ssize_t write(int fd, const void *buf, size_t count);
//fd: 文件描述句柄 
//buf: 内容
//count: 写的数目

(2) 返回值
成功:返回实际写入的字节数
失败:返回 -1, 错误编号设置到errno中,可用( strerror(errno) ) 查看

注意:是从文件的当前指针位置写入!
文件刚打开时,文件的位置指针指向 文件头
(3) 示例

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(void)
{
	int len = 0;

	char buff[] = "hello world\n";
	
	len = write(1, buff, sizeof(buff)); //标准输出设备(控制台)
	if(len < 0)
	{
		printf("write to stdout failed. reason: %s\n", strerror(errno));
	}
	else
	{
		printf("write %d bytes.\n", len);
	}
		
	write(2, buff, sizeof(buff)); //标准错误输出设备(控制台)
	return 0;
}

read

(1)用法

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
//fd: 文件描述句柄 
//buf: 内容
//count: 写的数目

//其他:man 2 read

(2)返回值

>0 : 实际读取的字节数
0 : 已读到文件尾
-1 :出错
注意:参数3表示最多能接受的字节数,而不是指一定要输入的字节数

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    char buffer[1024];
    int cnt = 0;

    cnt = read(0, buffer, sizeof(buffer));  //从键盘读

    write(1, buffer, cnt);  //写到控制台
    
    return 0;
}

运行:
#./a.out 控制台用户输入回车符时结束输入
#./a.out < L_read.c 利用重定向, 使用文件main.c作为输入
下图中将a.out命名-o read.exe
在这里插入图片描述
也可以重定向,写到别的文件中,箭头" > "即可
在这里插入图片描述

open

(1) 用法
打开或创建一个文件或设备

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

(2) 返回值
成功:文件描述符
失败:-1
(3) 打开方式
O_RDONLY : 只读
O_WRONLY: 只写
O_RDWR : 读写
O_CREAT : 如果文件不存在,则创建该文件,并使用第3个
参数设置权限,如果文件存在 ,则只打开文件

O_EXCL : 如果同时使用O_CREAT而且该文件又已经存在时,则返回错误, 用途:以防止多个进程同时创建同一个文件

O_APPEND : 尾部追加方式(打开后,文件指针指向文件的末尾)
O_TRUNC : 若文件存在,则长度被截为0,属性不变

参数3 (设置权限)
当使用O_CREAT时,使用参数3

S_I(R/W/X)(USR/GRP/OTH)
例:
S_IRUSR | S_IWUSR 文件的所有者对该文件可读可写
(八进制表示法)0600 文件的所有者对该文件可读可写

example:

 open("/dev/hello", O_RDONLY|O_CREAT|O_EXCL, 0777)   

注意:
返回的文件描述符是该进程未打开的最小的文件描述符

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define FILE_RW_LEN 1024

int main(void){
    int fd = 0;
    int count = 0;
    char buffer[FILE_RW_LEN]="I 'm Martin.";

fd = open("./martin.txt", O_CREAT|O_RDWR|O_APPEND|O_TRUNC,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
    //fd = open("./martin.txt", O_CREAT|O_EXCL|O_RDWR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);

    if(fd < 0){
        printf("open file martin.txt failed. reason: %s\n", strerror(errno));
        exit(-1);
    }
    
    count = write(fd, buffer, strlen(buffer));

    printf("written: %d bytes.\n", count);

    close(fd);
}

close

(1) 用法
man 2 close

终止指定文件描述符与对应文件之间的关联,
并释放该文件描述符,即该文件描述符可被重新使用

(2)返回值
成功: 0
失败: -1
观察耗时

./a.out
time  ./a.out   

补充:time命令

time命令分别输出:
real - 程序总的执行时间、
usr - 该程序本身所消耗的时间、
sys - 系统调用所消耗的时间 .

lseek

(1) 用法
man 2 lseek
用于文件读写的偏移(重新定位文件读写的位置)

    #include <sys/types.h>
    #include <unistd.h>
    
	off_t lseek(int fd, off_t offset, int whence);

fildes :

已打开的文件描述符

offset :

根据参数whence来移动读写位置的位移数

whence:

SEEK_SET 参数offset 即为新的读写位置.
SEEK_CUR 以目前的读写位置往后增加offset 个位移量.
SEEK_END 将读写位置指向文件尾后再增加offset 个位移量. 当whence 值为SEEK_CUR 或
SEEK_END 时, 参数offet 允许负值的出现.

使用方式:

  1. 欲将读写位置移到文件开头时:lseek(int fildes, 0, SEEK_SET);
  2. 欲将读写位置移到文件尾时:lseek(int fildes, 0, SEEK_END);
  3. 想要取得目前文件位置时:lseek(int fildes, 0, SEEK_CUR);

(2) 返回值
成功:返回新的文件位置与文件头之间偏移
失败: -1

demo
从文件偏移量100的位置拷贝100个字节到另一个文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define FILE1_NAME "lseek_demo.c"
#define FILE2_NAME "lseek_demo_2.c"

#define SIZE   100

int main(void){
    int file1, file2;
    char buffer[1024];
    int ret;

    file1 = open(FILE1_NAME, O_RDONLY);
    if (file1 < 0) {
        printf("open file %s failed\n", FILE1_NAME);
        exit(-1);
    }

    file2 = open(FILE2_NAME, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
    if (file2 < 0) {
        printf("open file %s failed\n", FILE2_NAME);
        exit(-1);
    }

    //file size
    ret = lseek(file1, 0, SEEK_END);
    printf("file size: %d\n", ret);

    ret = lseek(file1, 100, SEEK_SET);
    printf("lseek ret: %d\n", ret);

    ret = read(file1, buffer, SIZE);
    if(ret > 0){
        buffer[ret] = '\0';
        printf("read[%d]: %s\n", ret, buffer);
        write(file2, buffer, SIZE);
    }

    close(file1);
    close(file2);
    return 0;
}

ioctl

扩展补充:

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。是设备驱动程序中设备控制接口函数,用来控制设备.

函数名: ioctl

功 能: 控制I/O设备

用 法: int ioctl(int fd, int cmd,[int *argdx, int argcx]);

参数:fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,后面是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值