一、头文件 <sys/types.h>
头文件 <sys/types.h>
是一个标准 C 和 POSIX 头文件,包含了一些基本的系统数据类型定义。这些数据类型通常用于系统编程和文件 I/O 操作等低级编程任务。以下是 <sys/types.h>
中常见的一些数据类型:
-
size_t
:无符号整数类型,通常用于表示内存块的大小或数组的长度。 -
ssize_t
:有符号整数类型,通常用于表示函数调用的结果,如read
和write
函数的返回值,表示读取或写入的字节数。 -
off_t
:有符号整数类型,通常用于表示文件偏移量(文件中的位置)。 -
pid_t
:有符号整数类型,通常用于表示进程 ID(Process ID)。 -
uid_t
和gid_t
:无符号整数类型,用于表示用户 ID(User ID)和组 ID(Group ID)。 -
mode_t
:无符号整数类型,通常用于表示文件权限位。
这些数据类型的具体大小和范围可能会因操作系统和硬件平台而异,但它们在不同的系统上都有一定程度的标准化。程序员可以使用这些数据类型来编写与平台无关的系统级代码,以确保在不同的操作系统上具有可移植性。
此外,<sys/types.h>
还包含一些其他的数据类型和宏定义,用于处理文件描述符、套接字描述符等系统级概念。在进行系统编程或使用低级系统调用时,通常需要包含这个头文件来访问这些定义。
二、头文件<unistd.h>
<unistd.h>
是一个C标准库头文件,通常用于访问 POSIX 操作系统 API(Application Programming Interface)。它包含了一系列与系统调用(system call)和其他低级操作系统功能相关的函数、符号常量以及类型定义。
一些常见的功能和定义在 <unistd.h>
中包括:
-
文件操作函数:例如
read
、write
、close
,用于文件和文件描述符的读写和关闭操作。 -
进程控制函数:例如
fork
、exec
、exit
,用于创建进程、执行其他程序,以及终止进程。 -
文件和目录路径处理函数:例如
access
、chdir
、getcwd
,用于检查文件访问权限、切换当前工作目录,以及获取当前工作目录。 -
系统调用函数:例如
syscall
,用于执行底层系统调用,通常不直接使用,而是使用更高级别的函数来代替。 -
符号常量:例如
STDIN_FILENO
、STDOUT_FILENO
、STDERR_FILENO
,用于表示标准输入、标准输出和标准错误的文件描述符。 -
类型定义:例如
ssize_t
、off_t
、pid_t
,用于表示文件大小、文件偏移量、进程ID等数据类型。
<unistd.h>
主要用于Unix和Unix-like操作系统,例如Linux和macOS等,因此它在跨平台开发时需要谨慎使用,因为一些功能和常量在不同系统上可能会有差异。通常,它用于系统级编程,包括文件 I/O、进程管理和系统调用的处理。
三、头文件<sys/stat.h>
<sys/stat.h>
是一个C和C++标准库头文件,通常用于在Unix和类Unix操作系统上访问文件和文件属性的相关函数和数据结构。这个头文件定义了一些常见的文件和文件夹属性,以及一些用于操作这些属性的函数。
一些 <sys/stat.h>
中常用的函数和数据结构包括:
-
struct stat
结构体:用于表示文件或目录的属性,包括文件大小、访问权限、修改时间等。这个结构体的成员可以通过相应的函数获取,如stat()
、lstat()
、fstat()
等。 -
stat()
函数:用于获取指定文件的属性信息,并将结果存储在struct stat
结构体中。 -
lstat()
函数:类似于stat()
,但对于符号链接文件,它返回符号链接本身的属性,而不是目标文件的属性。 -
fstat()
函数:用于获取一个已经打开的文件描述符所指向文件的属性信息,并将结果存储在struct stat
结构体中。 -
文件访问权限宏:例如
S_IRUSR
(用户可读权限)、S_IWGRP
(用户组可写权限)等,用于设置和检查文件的权限。 -
文件类型宏:例如
S_IFREG
(常规文件)、S_IFDIR
(目录文件)等,用于检查文件的类型。 -
chmod()
函数:用于更改文件的权限。 -
chown()
函数:用于更改文件的所有者和所属用户组。 -
mkdir()
函数:用于创建新目录。 -
rmdir()
函数:用于删除目录。
这些函数和数据结构允许程序员在Unix和类Unix系统上查询和修改文件的属性,以及执行文件和目录的创建、删除、权限更改等操作。它们对于系统编程和文件操作非常有用。
四、lseek函数
lseek
函数用于在文件中设置文件偏移量,允许程序在文件中进行随机访问,而不必按照顺序进行读取或写入操作。这个函数在Unix和类Unix操作系统上非常有用,通常用于文件I/O操作。
/*
* 标准c库
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
linux系统函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
-fd : 文件描述符,通过open得到的,通过fd操作某个文件
-offset : 偏移量
-whence :
SEEK_SET
The file offset is set to offset bytes. 设置文件指针的偏移量
SEEK_CUR
The file offset is set to its current location plus offset bytes. 设置偏移量:当前位置 + 第二个参数offset的值
SEEK_END
The file offset is set to the size of the file plus offset bytes. 设置偏移量 :文件的大小 + 第二个参数offset的值
返回值: 返回文件指针的位置
作用:
1. 移动文件指针到文件头
lseek(fd,0,SEEK_SET);
2. 获取当前文件指针的位置
lseek(fd,0,SEEK_CUR);
3. 获取文件长度
lseek(fd,0,SEEK_END);
4. 拓展文件的长度,当前文件10b,110b,增加100个字节
lseek(fd,100,SEEK_END);
lseek()不是扩展数据的功能,只是可以利用lseek()去扩展文件,lseek()只是单纯的移动文件指针偏移。
拓展时,lseek只是逻辑上移动文件指针的位置,并没有为文件分配存储空间,为了让这些空间实际得到分配,可以使用write在最后补充一个字符,这样拓展的存储空间应该就分配了。
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
test1(){
int fd = open("F:\\C++\\C++\\c++linux\\linux_io_fun\\hello.txt",O_RDWR);
if(fd ==-1){
perror("open");
return -1;
}
// 扩展文件长度
int ret = lseek(fd,100,SEEK_END);
if(ret==-1){
perror("lseek");
return -1;
}
// 写入一个空数据
write(fd," ",1);
close(fd);
}
int main(){
test1();
return 0;
}