少女祈祷中...

文件读写相关函数

主要头文件为 fcntl.hunistd.h

函数名 函数作用说明
文件读写相关函数
open() 打开/创建文件
read() 读取文件
write() 写入文件
close() 关闭文件
lseek() 修改文件指针位置
文件权限与属性操作
chmod() 更改文件权限(如 chmod 755 file
chown() 更改文件所有者和组
stat() 获取文件的详细信息(大小、类型、权限等)
fstat() 获取已打开文件的属性(比 stat 快)
access() 检测文件是否存在、是否可读写执行
文件复制 / 重命名 / 删除 / 创建目录
rename() 重命名文件
unlink() 删除文件(等价于 rm
remove() 删除文件或空目录
mkdir() 创建目录
rmdir() 删除空目录
文件描述符控制
dup() / dup2() 复制文件描述符(常用于重定向)
fcntl() 控制文件描述符属性(如非阻塞 IO、加锁等)
ioctl() 设备控制接口(底层操作)
文件锁相关
flock() 文件级别锁
fcntl() 支持记录锁(对 read/write 区域加锁)
内存映射文件(高性能 I/O)
mmap() 将文件映射到内存,实现高效读取/写入
munmap() 解除映射
msync() 将内存中的更改同步到磁盘
异步与非阻塞 I/O(高级)
select() 多路复用(经典方式)
poll() 多路复用(更现代)
epoll_*() 高性能 IO 事件通知(Linux 专属)
aio_*() 异步 IO 系列函数(如 aio_read()
临时文件与随机访问
tmpfile() 创建匿名临时文件
pread() / pwrite() 支持带偏移量的读写(线程安全)

open() 函数

函数原型

1
2
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); // 创建文件时需要指定权限

参数说明

  • pathname:文件路径,例如 “./test.txt”。或者直接给文件名的字符串,将在当前路径打开/创建该文件
  • flags:打开方式(必须指定),可选如下组合:
    标志常量 含义
    O_RDONLY 只读方式打开
    O_WRONLY 只写方式打开
    O_RDWR 可读可写方式打开
    O_CREAT 如果文件不存在则创建文件
    O_EXCL 与 O_CREAT 一起使用,确保创建
    O_APPEND 每次写入追加到文件末尾
    O_TRUNC 打开文件时清空原有内容
    O_NONBLOCK 非阻塞方式打开文件
    O_SYNC 同步写入(立即写入磁盘)
  • mode:文件权限(仅在使用 O_CREAT 时需要),如 0666,是 Linux 中的权限掩码(掩码会受 umask 影响)。
    返回值
    成功:返回 文件描述符(非负整数),用于后续 read() / write() / close() 操作。
    失败:返回 -1,并设置 errno。

read() 函数

函数原型
ssize_t read(int fd, void *buf, size_t count);
参数分析

  • fd: 要读取的文件描述符。可以是通过 open() 打开的文件,也可以是其他 I/O 流。
  • buf: 存放读取内容的缓冲区指针。
  • count: 要读取的字节数。
    返回值分析
  • 成功时,返回读取的字节数。可能小于 count,表示文件末尾(EOF)。
  • 失败时,返回 -1,并设置 errno,表明错误。

write() 函数

函数原型
ssize_t write(int fd, const void *buf, size_t count);
参数分析

  • fd: 要写入的文件描述符。
  • buf: 存放要写入内容的缓冲区指针。
  • count: 要写入的字节数。
    返回值分析
  • 成功时,返回写入的字节数。可能小于 count,如果该文件是 O_APPEND 打开的,写入位置可能会改变。
  • 失败时,返回 -1,并设置 errno,表明错误。

close() 函数

函数原型
int close(int fd);
参数分析

  • fd: 要关闭的文件描述符。
    返回值分析
  • 成功时,返回 0。
  • 失败时,返回 -1,并设置 errno,表明错误。

lseek() 函数

函数原型
off_t lseek(int fd, off_t offset, int whence);
参数分析

  • fd: 文件描述符,指定要操作的文件。
  • offset: 偏移量,表示从当前位置开始的字节数。
  • whence: 偏移的起始位置,可以是以下值之一:
    • SEEK_SET: 从文件开头计算偏移。
    • SEEK_CUR: 从当前位置计算偏移。
    • SEEK_END: 从文件末尾计算偏移。
      返回值分析
  • 成功时,返回新的文件指针位置(即从文件开头的字节偏移量)。
  • 失败时,返回 -1,并设置 errno,表明错误。

综合示例–文件拷贝

执行 ./test [拷贝的文件地址] 将拷贝该文件,并打印源文件和拷贝文件的大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc,char* argv[]){

if(argc != 2){
printf("argc need file ");
return -1;
}

int fd = -1,fd_copy = -1;
char* filename = argv[1];
char filename_copy[20];
sprintf(filename_copy,"%s.copy",filename);

if((fd = open(filename,O_RDWR|O_CREAT,0666)) == -1){
printf("open or create file 2 error");
return -1;
}

if((fd_copy = open(filename_copy,O_RDWR|O_CREAT,0666)) == -1){
printf("open or create file 2 error");
return -1;
}

lseek(fd,0,SEEK_SET);
int re = 0,copysize = 0;
char readbuf[10] = {0};

while((re = read(fd,readbuf,10)) > 0){

if(write(fd_copy,readbuf,re) != re){
printf("write error");
return -1;
}
copysize += re;
printf("write content: %s\n ",readbuf);
}

// lseek(fd,0,SEEK_SET);
int filesize = lseek(fd,0,SEEK_END);

printf("file size :%d,copy size :%d\n",filesize,copysize);
close(fd);
return 0;
}

进程管理相关函数

函数名 函数作用及说明
fork() 用于创建一个子进程。父进程和子进程的代码会同时执行。返回值:在父进程中返回子进程的 PID,在子进程中返回 0。
exec() 用于执行一个程序,替换当前进程的映像。常见的有 execlp(), execvp() 等变种。返回值:成功时不返回,失败时返回 -1。
wait() 父进程调用,等待子进程结束。返回值:子进程的 PID,或 -1(如果没有子进程或出错)。
exit() 用于终止当前进程的执行,并返回一个退出状态码。返回值:无,进程结束后,操作系统会处理退出状态码。

fork() 函数

函数原型
pid_t fork(void);
返回值分析

  • 成功时,父进程返回子进程的 PID(大于 0),子进程返回 0。
  • 失败时,返回 -1,且 errno 被设置为错误码。
    说明
  • fork() 用于创建一个子进程。调用该函数后,父进程和子进程会从 fork() 处继续执行。父进程返回子进程的 PID,子进程返回 0。父子进程拥有各自的地址空间,文件描述符等资源的副本,但它们共享某些资源(如打开的文件描述符)。

exec() 函数系列

函数原型

1
2
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
int execp(const char *path, const char *arg, ... /* (char *) NULL */);

参数分析

  • path:要执行的程序的路径。
  • arg:传递给程序的参数列表,参数以 NULL 结尾。
    返回值分析
  • 成功时,exec() 不会返回,因为调用的程序会替换当前进程的映像。
  • 失败时,返回 -1,errno 会设置为错误码。
    说明
  • exec() 函数族用于加载和执行一个新的程序,替换当前进程的映像。常见的变种包括 execlp(), execvp() 等,它们在路径查找和参数传递上有所不同。

wait() 函数

函数原型
pid_t wait(int *status);
参数分析

  • status:指向整数的指针,用于接收子进程的退出状态码。
    返回值分析
  • 成功时,返回已退出的子进程的 PID。
  • 失败时,返回 -1,并设置 errno。
    说明
  • wait() 函数用于父进程等待子进程终止。该函数会阻塞父进程,直到某个子进程退出或收到某些信号。status 用来存储子进程的退出状态码,父进程可以通过该值判断子进程的结束方式(正常退出或异常退出)。

exit() 函数

函数原型
void exit(int status);
参数分析

  • status:进程的退出状态码,通常是整数值,表示进程的退出状态。
    返回值分析
  • 无返回值,调用该函数后,进程将终止。
    说明
  • exit() 用于终止当前进程的执行。退出状态码会传递给父进程,通常用于标识进程的结束情况(如成功、失败等)。调用 exit() 后,操作系统会清理进程资源并关闭文件描述符。

综合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
pid_t pid = fork();

if (pid == 0) {
printf("this is child process\n");
execlp("ls", "ls", "-l", NULL);
perror("execlp error");
exit(-1);
} else if (pid > 0) {
printf("this is father process\n");
int status = 0;
wait(&status);
printf("child process exit status: %d\n", status);
} else {
perror("create process error");
}

return 0;
}

信号处理 相关函数

头文件 signal.h

函数名 函数作用及说明
signal() 设置信号的处理方式,如自定义处理函数、忽略信号或默认处理。
kill() 向指定进程或进程组发送信号,可用于终止进程、发送自定义信号等。
alarm() 设置一个定时器,若到达设定的秒数则发送 SIGALRM 信号给当前进程。
pause() 使进程挂起,直到接收到一个信号并且该信号的处理函数执行完毕。

signal() 函数

函数原型
void (*signal(int signum, void (*handler)(int)))(int);
参数分析

  • signum:要捕捉或处理的信号编号,如 SIGINT、SIGTERM 等。
  • handler:信号处理函数的指针,也可以是 SIG_IGN(忽略信号)或 SIG_DFL(默认处理)。
    返回值分析
  • 返回前一次为该信号设置的处理函数指针。如果出错,返回 SIG_ERR。

kill() 函数

函数原型
int kill(pid_t pid, int sig);
参数分析

  • pid:目标进程 ID,或 0(当前进程组)、-1(所有进程)等特殊值。
  • sig:要发送的信号编号,如 SIGINT、SIGKILL。
    返回值分析
  • 成功返回 0
  • 失败返回 -1,并设置 errno。

alarm() 函数

函数原型
unsigned int alarm(unsigned int seconds);
参数分析

  • seconds:在多少秒后触发 SIGALRM 信号。如果设为 0,则取消之前的 alarm。
    返回值分析
  • 返回之前设置的还剩多少秒的 alarm,如果没有则为 0。

pause() 函数

函数原型
int pause(void);
参数分析

  • 无参数。进程会挂起,直到捕捉到信号并从信号处理函数返回。
    返回值分析
  • 永远返回 -1,并将 errno 设置为 EINTR(被信号中断)。

综合示例

1、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void sig_handle(int sig) {
printf("Alarm triggered!\n");
}

int main() {
signal(SIGALRM, sig_handle);
alarm(3); // 设置 3 秒后触发 SIGALRM
pause(); // 等待信号
return 0;
}

2、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

#include <signal.h>

int mysig = 0;
void sighandle(int sig){
mysig = 1;
}

int main(int arg,char* argv[]){

pid_t pid = fork();

if(pid == 0){
printf("this is child process\n");

int cnt = 0;

signal(SIGINT,sighandle);
while(1){
if(mysig){
mysig = 0;
printf("Receive Ctrl+c\n");
}
printf("running:%d\n",cnt++);
sleep(1);
if(cnt == 13)exit(0);
}
}
else if(pid>0){
printf("this is father process\n");
signal(SIGINT, SIG_IGN);
sleep(5);
printf("father:send signal stop\n");
kill(pid,SIGSTOP);

sleep(5);
printf("father:send signal continue\n");
kill(pid,SIGCONT);

int statue = 0;
wait(&statue);
printf("child process exit statue:%d\n",statue);
}
else{
perror("create process error\n");
}
return 0;
}