抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

标准C库IO函数

1.7 文件IO_页面_02

自带帮助文档 第三章

image-20220310201130115

1.7 文件IO_页面_03

虚拟地址空间

1.7 文件IO_页面_05

Linux系统IO函数

帮助文档 ~Linux : man 2 open

停留在函数上Shif + k可进行快速跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 为社么定义三个头文件:不同的宏定义在两个文件里
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 宏 flags = 标记(只读、可读、可读可写 ...)
// 打开一个已经存在的文件
int open(const char *pathname, int flags);
参数:
- pathname : 要打开的文件路径
- flags : 对文件的操作权限还有其的他设置
O_RDONLY (只读), O_WRONLY (只写), O_RDWR (可读可写) 这三个是互斥的
返回值:返回一个新的文件描述符,如果失败了返回 -1 ,否则返回一个整形文件描述符
errno:属于Linux系统函数库,库里的一个全局变量,记录的是最近的错误号。
#include <stdio.h>
void perror(const char *s); 作用:打印errno对应的错误描述
参数:用户描述,比如hello,最终点输出的内容是 hello:xxx(实际的错误描述)


// 创建一个新的文件
int open(const char *pathname, int flags, mode_t mode);

没有创建 a.txt 代码

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
/*************************************************************************
> File Name: open_test1.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月11日 星期五 22时30分53秒
************************************************************************/

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

int main() {

int fd = open("a.txt", O_RDONLY);

if(fd == -1) {
perror("open");
}
// 读写操作

// 关闭一个文件描述符
close(fd);
return 0;
}

创建文件 touch a.txt

设置umask umask 022

image-20220312141638478

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
53
/*************************************************************************
> File Name: open_test1.c
> Author:
> Mail:
> Created Time: 2022年03月11日 星期五 22时30分53秒
************************************************************************/

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

/*
* int open(const char *pathname, int flags, mode_t mode);
* 参数 :
* - pathname : 要创建的文件路径
* - flags : 对文件操作的权限和其他的设置
* - 必选项 : O_RDONLY, O_WDONLY, O_WEONLY 这三个互斥
* - 可选项 :O_CREAT (文件不存在,创建新文件)
* - mode : 八进制的数, 表示创建出的新的文件的操纵权限, 例如:0775 (0开头表示 八进制)
* RWX(读、写、 可执行、三组 当前用户的权限、当前用户所在祖的权限、其他组) = 777
* 最终的权限是 : mode & ~umask(0002) // 不同用户不一样 这个值也能 更改
* 八进制 -> 二进制
* 0777 -> 111 111 111
* & 0775 -> 111 111 101
* --------------------------
* 111 111 101
* 按位与:0和任何数都为0
*
* umask : 作用就是抹去某些权限
* flags : 或的作用
* 参数是一个int类型的数据,占4个字节32位。
* 32个位,每一位就是一个标志位。
* 1 - R
* 2 - W
* 3 - RW
* 4 - CR
* */

int main() {

// 创建一个新的文件
int fd = open("create.txt", O_RDWR | O_CREAT, 0777);

if(fd == -1) {
perror("open");
}

// 关闭
close(fd);
return 0;
}

1.7 文件IO_页面_06

帮助文档 : man 2 copy

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*************************************************************************
> File Name: copyfile.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月17日 星期四 20时48分17秒
************************************************************************/
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/*
*
* #include <unistd.h>
* ssize_t read(int fd, void *buf, size_t count);
* 参数:
* - fd: 文件描述符, open得到的,通过这个文件描述符操作某个文件
* - buf: 缓冲区读取数据存放的地方数组的地址 (传出参数)
* - count: 指定的数组大小
* 返回值:
* - 成功:
* > 0: 返回实际的读取到的字数
* = 0: 文件已经读取完
* - 失败: - 1, 并设置errno
* #include <unistd.h>
* ssize_t write(int fd, const void *buf, size_t count);
* 参数:
* - fd: 文件描述, open得到的,y通过这个
* - buf: 要往磁盘写入的数据
* - count: 要写的数据的实际大小
* 返回值:
* 成功: 实际写入的大小
* 失败: 返回-1,并设置errno
*
*/

int main() {

// 1.通过open打开english.txt // 相对路径"文件名.后缀" // 绝对路径"c:/xxx/xxx/文件名.后缀"

int srcfd = open("english.txt", O_RDONLY);
if(srcfd == -1) {
perror("opne");
return -1;
}
// 2.创建一个新的文件(拷贝文件)

int destfd = open("cpy.txt", O_WRONLY | O_CREAT, 0664);
if(destfd == -1) {
perror("open");
return -1;
}

// 3.频繁的读写操作

char buf[1024] = {0};

int len = 0;
while((len = read(srcfd, buf, sizeof(buf))) > 0) {
// destfd: 目标文件文件描述符
write(destfd, buf, len);
}

// 4.关闭文件
close(destfd);
close(srcfd) ;
return 0;
}

帮助文档 : man 2 lseek

Linux 的 lseek 在标准c库中 man 3 fseek

为什么要扩展

比如说下载一个大小文件大小为5G(下载时候也正在用磁盘)假如磁盘大小么有5G(就不能正确下载下来)所以会提起占用一点点在替换

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*************************************************************************
> File Name: lseek.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月20日 星期日 16时40分30秒
************************************************************************/

/*
* 标准c库
* #inline <stdio.h>
* int fseek(FLE *stream, long offset, int whence);
*
* Linux系统函数
* #include <sys/types.h>
* #include <unistd.h>
* oof_t lseek(int fd, oof_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.
* 设置偏移量: 文件大小 + 第 二个参数offse的值
* 返回值: 返回文件指针的位置
* 作用:
* 1.移动文件指针
* lseek(fd, 0, SEEL_SET);
*
* 2.获取当前文件指针位置
* lseek(fd, 0, SEEK_CUR);
*
* 3.可以获取文件长度
* lseek(fd, 0, SEEK_END);
*
* 4.拓展文件的长度,当文件10b, 110b, 增加了100个字节
* lseek(fd, 100, SEEK_END);
* // 注意:需要些一次数据
*/


#include <stdio.h>

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

int main() {
int fd = open("hello.txt", O_RDWR);

if(fd == -1) {
perror("open");
return -1;
}

// 扩展文件的长度
int ret = lseek(fd, 100, SEEK_END);
if(ret == -1) {
perror("open");
return -1;
}

// 写入一个空格数据
write(fd, " ", 1);

// 关闭文件
close(fd);

return 0;
}

帮助文档 : man 2 stat

image-20220324203138161

image-20220324214627428

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
/*************************************************************************
> File Name: stat.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月23日 星期三 16时29分33秒
************************************************************************/

/*
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *statbuf);
作用: 获取一个文件相关的一些信息
参数;
- pathname: 操作文件的路径
- statbuf: 结构体变量, 传出参数, 用于保存获取的文件信息
返回值:
成功: 返回0
失败: 返回-1, 并设置errno
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

*/

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

int main() {

struct stat statbuf;

int ret = stat("a.txt", &statbuf);
if(ret == -1) {
perror("stat");
return -1;
}

printf("size: %ld\n", statbuf.st_size);

return 0;
}

模拟实现 ls -l 命令

参考文档 man 3 getpwuid

参考文档 man 3 getgrgid

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*************************************************************************
> File Name: ls-l.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月26日 星期六 15时29分49秒
-***********************************************************************/

// 模拟实现 ls -l 指令
// -rw-r--r-- 1 qz qz 11 3月 26 15:30 a.txt

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <string.h>

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

// 判断输入的参数是否正确
if(argc < 2) {
printf("%s filename\n", argv[0]);
return -1;
}

// 通过stat函数获取用户传入的文件信息
struct stat st;
int ret = stat(argv[1], &st);
if(ret == -1) {
perror("stat");
return -1;
}

// 获取文件类型和文件权限
char *perms = (char *)calloc(sizeof(char), 11);
switch(st.st_mode & S_IFMT) {
case S_IFLNK:
perms[0] = 'l';
break;
case S_IFDIR:
perms[0] ='d';
break;
case S_IFREG:
perms[0] ='-';
break;
case S_IFBLK:
perms[0] ='b';
break;
case S_IFCHR:
perms[0] ='c';
break;
case S_IFSOCK:
perms[0] ='s';
break;
case S_IFIFO:
perms[0] ='p';
break;
default:
perms[0] = '?';

}

// 判断文件的访问权限

// 文件所有者
perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';

// 文件所有组
perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';

// 其他人
perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';

// 硬链接数
int linkNum = st.st_nlink;

// 文件所有者
char *fileUser = getpwuid(st.st_uid)->pw_name;
// 文件所在组
char *fileGrp = getgrgid(st.st_gid)->gr_name;
// 文件大小
long int fileSize = st.st_size;
// 修改的时间 从 1970年 会自带一个换行
char *time = ctime(&st.st_mtime);

char mtime[512] ={0};
strncpy(mtime, time, strlen(time) - 1);

char buf[1024];
sprintf(buf, "%s %d %s %s %ld %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);
printf("%s\n", buf);
return 0;
}

文件属性

man 2 access

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
/*************************************************************************
> File Name: chmod.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月27日 星期日 11时21分04秒
************************************************************************/

/*
include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
修改文件的权限
参数:
- pathname: 需要修改的文件路径
- mode: 需要修改的权限值, 八进制的数
返回: h成功返回0, 失败返回-1

*/

#include <stdio.h>
#include <sys/stat.h>

int main() {
int ret = chmod("a.txt", 0775);

if(ret == -1) {
perror("chmod");
return -1;
}

return 0;
}

man 2 truncate

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
/*************************************************************************
> File Name: truncate.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月27日 星期日 17时35分17秒
************************************************************************/

/*
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
作用: 缩减或者扩展文件的尺寸至指定的大小
参数:
- path: 需要修改的文件的k路径
- length: 需要最终文件变成的大小
如果 一个文件(10K) 想变成一个(5k)就会把后面截取掉
返回: 成功0,失败-1

*/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {

int ret = truncate("b.txt", 20);
// int ret = truncate("b.txt", 5);
if(ret == -1) {
perror("truncat");
return -1;
}

return 0;
}

目录操作函数

man 2 mkdir

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
/*************************************************************************
> File Name: mkdir.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月28日 星期一 11时39分42秒
************************************************************************/

/*
include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
作用: 创建一个目录
参数:
pathname: 创建的目录的路径
mode: 权限, 八进制
返回:
成功返回0, 失败返回-1

// 删除
int rmdir(const char *pathname);

// 更名 第一个参数旧的名字 第二个参数新的名字
int rename(const char *oldpath, const char *newpath);


*/

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

int main() {
// 0777 0是八进制
// 一定要有可执行权限 x 要不就永不了 你不信试试
int ret = mkdir("aaa", 0777);
if(ret == -1) {
perror("mkdir");
return -1;
}
return 0;
}

man 2 getcwd 工作路径

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*************************************************************************
> File Name: getcwd.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月29日 星期二 09时27分16秒
************************************************************************/

/*
#include <unistd.h>
int chdir(const char *path);
作用: 修改进程的工作目录
比如在/home/root 启动了一个可执程序 a.out, 进程的工作目录
参数:
path: 需要修改的工作目录

#nclude <unistd.h>
char *getcwd(char *buf, size_t size);
作用: 获取当前工作目录
参数:
- buf: 存储的路径, 指向的是一个数组(传出参数)
- size: 数组大小
返回值:
返回的指向的一块内存, 这个数据就是第一个参数

*/

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

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

int main() {

// 获取当前工作目录
char buf[128];
getcwd(buf, sizeof(buf));
printf("当前的工作目录是 : %s\n", buf);

// 修改工作目录 下面是相对路径 不是绝对路径
int ret = chdir("../test");
if(ret == -1) {
perror("chdir");
return -1;
}

// 创建一个新的文件
int fd = open("w.txt", O_CREAT| O_RDWR, 0664);
if(fd == -1) {
perror("open");
return -1;
}

// 关闭文件描述符
close(fd);

// 获取当前工作目录
char buf1[128];
getcwd(buf1, sizeof(buf1));
printf("当前的工作目录是 : %s\n", buf1);


return 0;
}

man 3 opendir

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*************************************************************************
> File Name: readFileNum.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月30日 星期三 10时01分49秒
************************************************************************/


/*
// 打开目录
#nclude <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
参数:
- name: 需要打开的目录名称
返回值:
DIR * 类型理解为目录流
失败返回 NULL

// 读取目录中的数据
#include <dirent.h>
struct diren *readdir(DIR *dirp);
参数:
- dirp 是 opendir 返回的结果
返回值:
struct dirent 代表读取到的文件的信息
读取到了末尾或者失败了, 返回NULL

// 关闭目录
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);


*/

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>

int getFileNum(const char *path);

// 读取某个目录下的普通文件的个数
int main(int argc, char *argv[]) {

if(argc < 2) {
printf("%s path\n", argv[0]);
return -1;
}

int num = getFileNum(argv[1]);
printf("普通文件的个数: %d \n", num);

return 0;
}

// 用于获取目录下所有普通文件的个数
int getFileNum(const char *path) {

// 打开目录
DIR *dir = opendir(path);

if(dir == NULL) {
perror("opendir");
exit(0);
}

struct dirent *ptr;

// 记录普通文件的个数
int total = 0;

while((ptr = readdir(dir)) != NULL) {
// 获取名称
char *dname = ptr->d_name;

// 忽略掉 .和 ..
if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) continue;

// 判断是否是普通文件
if(ptr->d_type == DT_DIR) {
// 目录, 需要继续读取这个目录
char newpath[256];
sprintf(newpath, "%s%s", path, dname);
total += getFileNum(newpath);

}

if(ptr->d_type == DT_REG) {
// 普通文件
total++;
}
}
// 关闭目录
closedir(dir);
return total;
}

dup,dup2函数

man 2 dup

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
/*************************************************************************
> File Name: dup.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月30日 星期三 16时03分03秒
************************************************************************/

/*
* #include <unistd.h>
* int dup(int oldfd);
* 作用: 复制一个新的文件描述符
* fd = 3, fd1 = dup(fd);
* fd指向的是a.txt, fd1也是指向的a.txt
* 从空闲的文件描述符表中找到一个最小的, 作为新的拷贝的文件描述 符
*
*
*/

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

// 创建文件
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int main() {
// 第一个读写 第二创建
int fd = open("a.txt", O_RDWR | O_CREAT, 0664);

int fd1 = dup(fd);

if(fd1 == -1) {
perror("dup");
return -1;
}

printf("fd : %d \n fd1 : %d", fd, fd1);
close(fd);
char *str = "hello, world";
int ret = write(fd1, str, strlen(str));

if(ret == -1) {
perror("write");
return -1;
}
close(fd1);
return 0;
}

man 2 dup2

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
53
54
55
56
57
58
59
60
61
/*************************************************************************
> File Name: dup2.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月31日 星期四 14时25分22秒
************************************************************************/

/*
* #include <unistd.h>
* int dup2(int oldfd, int newfd);
* 作用: 重定向文件描述符
* oldfd 指向 a.txt, newfd 指向 b.txt
* 调用函数成功后: newfd 和 b.txt 做 close(), newfd 指向了 a.txt
* oldfd 必须是一个有效的文件描述符
* oldfd 和 newfd 值相同相当于什么也没做
*/

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

int main() {

int fd = open("1.txt", O_RDWR | O_CREAT, 0664);
if(fd == -1) {
perror("open");
}

int fd1 = open("2.txt", O_RDWR | O_CREAT, 0664);
if(fd == -1) {
perror("open");
return -1;
}

printf("fd : %d, fd1 : %d\n", fd, fd1);

int fd2 = dup2(fd, fd1);

if(fd2 == -1) {
perror("dup2");
return -1;
}

// 通过fd1去写数据, 实际操作的是1.txt, 而不是2.txt
char * str = "hello, dup2";
int len = write(fd1, str, strlen(str));
if(len == -1) {
perror("write");
return -1;
}

printf("fd : %d, fd1 : %d, fd2 : %d \n", fd, fd1, fd2);

close(fd);
close(fd1);

return 0;
}

man 2 fucnt

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*************************************************************************
> File Name: fcntl.c
> Author: 秃头王
> Mail: 1658339000@qq.com
> Created Time: 2022年03月31日 星期四 18时55分53秒
************************************************************************/

/*
* #include <unistd.h>
* #include <fcntl.h>
*
* int fcntl(int fd, int cmd, ...);
* 参数:
* - fd: 表示需要操作的文件描述符
* - cmd: 表示文件描述符进行如何操作
* 1. F_DUPFD: 复制文件描述符,复制的是一个参数fd,得到一个新的
* int ret = fcntl(fd, F_DUPFD);
* 2. F_GETFL: 获取指定的文件描述符文件状态flag
* 获取的flag和通过open函数传递的flag是一个东西
* 3. F_SETFL: 设置文件描述符文件状态falg
* 必选项: O_RDONLY, O_WRODNLY, O_RDWR 不可以被修改
* 可选性: O_APPEND, O_NONBLOCK
* O_APPEND: 表示追加数据
* O_NONBLOCK: 设置成非阻塞
* 阻塞和非阻塞: 指的是函数调用的行为。add()
*/

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main() {

// 1.复制文件描述符
// int fd = open("1.txt", O_RDONLY);

// int ret = fcntl(fd, F_DUPFD);

// 2.修改或者获取文件状态flag --- 当前文件只读
int fd = open("1.txt", O_RDWR);
if(fd == -1) {
perror("open");
return -1;
}

// 获取文件描述符状态
int flag = fcntl(fd,F_GETFL);
if(flag == -1) {
perror("fcntl_GET");
return -1;
}
flag |= O_APPEND;

// 修改文件描述符状态的flag, 给flag加入O_APPEND这个标记
int ret = fcntl(fd, F_SETFL, flag);

if(ret == -1) {
perror("fcntl_SET");
return -1;
}

char *str = "nihao";
write(fd, str, strlen(str));

close(fd);

return 0;
}

评论