#Linux C 文件编程 ###文件操作 ####open
打开文件
header#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
declareint open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);
args
path: 准备打开的文件或设备名字.
oflags: 指出要打开文件的访问模式.
O_RDONLY [3选1] 只读方式打开
O_WRONLY [3选1] 只写方式打开
O_RDWR [3选1] 读写方式打开
O_APPEDN [可选] 追加方式打开
O_TRUNC [可选] 将文件长度设为零, 丢弃之后内容.
O_CREAT [可选] 按参数mode中给出的访问模式创建文件.
O_EXCL [可选] 和O_CREAT一起用, 如果文件已存在, open调用失败.
O_NONBLOCK [可选] 非阻塞方式打开文件
mode: 用O_CREAT标志的open来创建文件时赋予权限.
S_IRUSR 读权限 文件属主
S_IWUSR 写权限 文件属主
S_IXUSR 执行权 文件属主
S_IRGRP 读权限 文件属组
S_IWGRP 写权限 文件属组
S_IXGRP 执行权 文件属组
S_IROTH 读权限 其他用户
S_IWOTH 写权限 其他用户
S_IXOTH 执行权 其他用户
也可以使用数字0777[全权限]来设置
return
success: fd 打开的文件描述符
error: -1 ####close
关闭文件 header#include <unistd.h>
declareint close(int fd);
args
fd: 要关闭的文件描述符
return
success:0 error: -1
####read
读取文件
header#include <unistd.h>
declaresize_t read(int fd, void *buf, size_t nbytes);
args
fd: 文件描述符
buf: 用来存储读入的数据的缓冲区
nbytes: 读取的字符数
return
success: n 读取的字符数
error: -1
####write
写入文件 header#include <unistd.h>
declaresize_t write(int fd, const void *buf, size_t nbytes);
args
fd: 文件描述符
buf: 待写入的字符串
nbytes: 写入的字符数
return
success: 写入的字符数
error: -1
####lseek
设置文件描述符指针位置
header#include <unistd.h>
#include <sys/types.h>
declareoff_t lseek(int fd, off_t offset, int whence);
args
fd: 文件描述符
off_set: 指定位置
whence: 参数定义该偏移值的用法
SEEK_SET: 文件头的绝对位置
SEEK_CUR: 当前位置的相对位置
SEEK_END: 文件尾的相对位置
return
success: 返回文件到文件指针被设置处的字节偏移 error: -1
####stat
获取文件元数据
header#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
declareint fstat(int fd, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
lstat 通过文件路径获取软链接文件元数据
stat 通过文件路径获取文件元数据
fstat 通过文件描述服来获取文件元数据
args
fd: 文件描述符
path: 文件路径
buf: 获取文件元数据的结构体指针
return
success: 0
error: -1
####dup
复制文件描述符
header#include <unistd.h>
declareint dup(int fd);
int dup2(int fd,int fd2);
dup 根据fd返回一个新的文件描述符
dup2 明确指定描述符
args
fd: 文件描述符
fd2: 新文件描述符
return
success: 新文件描述符
error: -1
####getcwd
获取当前工作目录 header#include <unistd.h>
declarechar* getcwd(char *buf, size_t size);
args
buf: 目录路径
size: buf空间大小
return
success: 指向工作目录的指针
error: NULL
####chdir
改变当前目录到指定目录 header#include <unistd.h>
declareint chdir(const char *path);
args
path: 目录路径
return
success: 0
error: -1
####chroot
改变根目录到指定目录 header#include <unistd.h>
declareint chroot(const char *path);
args
path: 目录路径
return
success: 0
error: -1
目录操作
####mkdir
创建目录
header#include <sys/stat.h>
#include <sys/types.h>
declareint mkdir(const char *filename, mode_t mode);
args
filename: 目录路径
mode: 权限
return
success: 0
error: -1
####rmdir
删除目录
header#include <unistd.h>
declareint rmdir(const char *filename);
args
filename: 目录路径
return
success: 0
error: -1
####opendir
打开目录
header#include <sys/types.h>
#include <dirent.h>
declareDIR *opendir(const char *path);
args
path: 路径
return
success: DIR指针
error: NULL
####closedir
关闭目录
header#include <sys/types.h>
#include <dirent.h>
declareint closedir(DIR *dir);
args
dir: DIR指针
return
success: 0
error: -1
####readdir
获取目录信息
header#include <sys/types.h>
#include <dirent.h>
declarestruct dirent *readdir(DIR *dir);
args
dir: DIR指针
return
success: dirent结构体指针
error: NULL
###其他操作
####chmod
改变文件/目录权限 header#include <sys/stat.h>
declareint chmod(const char *path, mode_t mode);
args
path: 路径
mode: 权限
return
success: 0
error: -1
####chown
改变文件/目录属主和属组
header#include <unistd.h>
declareint chown(const char *path, uid_t owner, gid_t group);
args
path: 路径
owner: 属主
group: 属组
return
success: 0
error: -1
####link
链接相关操作
header#include <unistd.h>
declareint link(const char *oldpath, const char *newpath);
int symlink(const char *oldpath, const char *newpath);
int unlink(const char * path );
link 硬链接一个文件
symlink 软链接一个文件
unlink 删除文件的一次硬链接[删除文件]
args
oldpath: 被链接的文件
newpath: 新文件路径
path: 路径
return
success: 0
error: -1
####umask
改变文件/目录权限掩码 header#include <sys/stat.h>
#include <sys/types.h>
declaremode_t umask(mode_t mode);
args
mode: 权限
return
success: 之前的权限掩码
##库函数和系统调用的区别 ###库函数调用 #include <stdio.h>
移植性好 C库函数相同
属于过程调用 开销较小
C标准库默认分配了3个文件流 `FILE*`类型
stdin: 标准输入
stdout: 标准输出
stderr: 标准错误输出
###系统调用 #include <unistd.h>
移植性差 各个操作系统的系统调用不同
需要在用户空间和内核上下文环境间切换 开销较大
Linux系统默认分配了3个文件描述符值
0: 标准输入
1: 标准输出
2: 标准错误输出
例子1 简单cp命令的实现
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#define MAXLINE 80
void if_error(int status_code, char *err_msg)
{
if (status_code < 0) {
perror(err_msg);
exit(errno);
}
}
int main(int argc, char **argv)
{
int fd_read, fd_write, n;
char buf[MAXLINE];
fd_read = open("/etc/passwd", O_RDONLY);
if_error(fd_read, "open_read");
fd_write = open("./test_passwd", O_WRONLY|O_CREAT, 0664);
if_error(fd_write, "open_write");
while ((n = read(fd_read, buf, MAXLINE)) > 0) {
write(fd_write, buf, n);
write(STDOUT_FILENO, buf, n);
}
//unlink("./test_passwd");
return 0;
}
例子2 获取文件的属性
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void if_error(int status_code, char *err_msg)
{
if (status_code < 0) {
perror(err_msg);
exit(errno);
}
}
void get_perm(char *filename)
{
struct stat buf;
int ret = stat(filename, &buf);
if_error(ret, "stat");
if (buf.st_mode & S_IRUSR)
printf("owner can read %s\n", filename);
if (buf.st_mode & S_IWUSR)
printf("owner can write %s\n", filename);
if (buf.st_mode & S_IRGRP)
printf("group can read %s\n", filename);
if (buf.st_mode & S_IWGRP)
printf("group can write %s\n", filename);
if (buf.st_mode & S_IROTH)
printf("others can read %s\n", filename);
if (buf.st_mode & S_IWOTH)
printf("others can write %s\n", filename);
printf("\n");
}
int main(int argc, char **argv)
{
int i;
char *filename[3] = {"/etc/passwd", "/tmp/"};
for (i = 0; i < 2; i++)
get_perm(filename[i]);
return 0;
}
例子3 递归列出目录下所有文件
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MAXLINE 80
void if_null(void *ptr, char *err_msg)
{
if (ptr == NULL) {
perror(err_msg);
exit(errno);
}
}
void list_file(char *path)
{
DIR *dir;
struct dirent *file;
struct stat info;
char buf[MAXLINE];
dir = opendir(path);
if_null(dir, "opendir");
while((file = readdir(dir)) != NULL) {
/* ignone . and .. */
if(!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
continue;
sprintf(buf ,"%s/%s", path, file->d_name);
lstat(buf, &info);
if (S_ISDIR(info.st_mode)) {
list_file(buf);
} else {
printf("%s\n", file->d_name);
}
}
closedir(dir);
}
int main(int argc, char **argv)
{
list_file("/boot");
return 0;
}