linux系统编程之文件和目录操作-爱代码爱编程
目录
01. 学习目标
- 了解概念: pcb和文件描述符,虚拟地址空间
- 了解Linux系统常用IO函数(暂不要求能够使用)
- 熟练掌握Linux系统IO函数的使用
- 了解阻塞和非阻塞的概念
- 掌握dup、dup2函数的使用
- 熟练掌握Linux系统IO函数的使用
- 掌握stat/lstat函数的使用
- 掌握fcntl函数的使用
02. 文件操作相关函数
2.1 stat函数(重点)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
功能:
获取文件状态信息
stat和lstat的区别:
当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;
而stat返回的是该链接指向的文件的信息。
参数:
path:文件名
buf:保存文件信息的结构体
返回值:
成功: 0
失败: -1
struct stat结构体说明:
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
blksize_t st_blksize; //块大小(文件系统的I/O 缓冲区大小)
blkcnt_t st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
st_mode(16位整数)参数说明
文件类型判断应使用宏函数
测试程序:
int main()
{
struct stat buf;
stat("a.txt", &buf);
if (S_ISREG(buf.st_mode))
{
printf("%s\n", "这是普通文件");
}
return 0;
}
2.2 access函数
#include <unistd.h>
int access(const char *pathname, int mode);
功能:测试指定文件是否具有某种属性
参数:
pathname:文件名
mode:文件权限,4种权限
R_OK: 是否有读权限
W_OK: 是否有写权限
X_OK: 是否有执行权限
F_OK: 测试文件是否存在
返回值:
0: 有某种权限,或者文件存在
-1:没有,或文件不存在
access("txt", F_OK);
2.3 chmod函数
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
功能:修改文件权限
参数:
filename:文件名
mode:权限(8进制数)
返回值:
成功:0
失败:-1
2.4 chown函数
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
功能:修改文件所有者和所属组
参数:
pathname:文件或目录名
owner:文件所有者id,通过查看 /etc/passwd 得到所有者id
group:文件所属组id,通过查看 /etc/group 得到用户组id
返回值:
成功:0
失败:-1
2.5 truncate函数
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
功能:修改文件大小
参数:
path:文件文件名字
length:指定的文件大小
a)比原来小, 删掉后边的部分
b)比原来大, 向后拓展
返回值:
成功:0
失败:-1
2.6 link函数
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
功能:创建一个硬链接
参数:
oldpath:源文件名字
newpath:硬链接名字
返回值:
成功:0
失败:-1
2.7 symlink函数
#include <unistd.h>
int symlink(const char *target, const char *linkpath);
功能:创建一个软链接
参数:
target:源文件名字
linkpath:软链接名字
返回值:
成功:0
失败:-1
2.8 readlink函数
2.9 unlink函数
#include <unistd.h>
int unlink(const char *pathname);
功能:删除一个文件(软硬链接文件)
参数:
pathname:删除的文件名字
返回值:
成功:0
失败:-1
2.10 rename函数
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
功能:把oldpath的文件名改为newpath
参数:
oldpath:旧文件名
newpath:新文件名
返回值:
成功:0
失败:-1
03. 文件描述符复制(重点)
3.1 概述
dup() 和 dup2() 是两个非常有用的系统调用,都是用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。
这个过程类似于现实生活中的配钥匙,钥匙相当于文件描述符,锁相当于文件,本来一个钥匙开一把锁,相当于,一个文件描述符对应一个文件,现在,我们去配钥匙,通过旧的钥匙复制了一把新的钥匙,这样的话,旧的钥匙和新的钥匙都能开启这把锁。
对比于 dup(), dup2() 也一样,通过原来的文件描述符复制出一个新的文件描述符,这样的话,原来的文件描述符和新的文件描述符都指向同一个文件,我们操作这两个文件描述符的任何一个,都能操作它所对应的文件。
3.1 dup函数
#include <unistd.h>
int dup(int oldfd);
功能:
通过 oldfd 复制出一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终 oldfd 和新的文件描述符都指向同一个文件。
参数:
oldfd : 需要复制的文件描述符 oldfd
返回值:
成功:新文件描述符
失败: -1
3.2 dup2函数
#include <unistd.h>
int dup2(int oldfd, int newfd);
功能:
通过 oldfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终 oldfd 和新的文件描述符 newfd 都指向同一个文件。
参数:
oldfd : 需要复制的文件描述符
newfd : 新的文件描述符,这个描述符可以人为指定一个合法数字(0 - 1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭 close() 断开这个数字和某个文件的关联,再来使用这个合法数字。
返回值:
成功:返回 newfd
失败:返回 -1
3.3 示例分析
04. fcnlt函数
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
功能:改变已打开的文件性质,fcntl针对描述符提供控制。
参数:
fd:操作的文件描述符
cmd:操作方式
arg:针对cmd的值,fcntl能够接受第三个参数int arg。
返回值:
成功:返回某个其他值
失败:-1
fcntl函数有5种功能:
1) 复制一个现有的描述符(cmd=F_DUPFD)
2) 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
3) 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL)
4) 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)
5) 获得/设置记录锁(cmd=F_GETLK, F_SETLK或F_SETLKW)
参考示例:
// 等价于dup()
int new_fd = fcntl(fd, F_DUPFD, 0);
// 获取文件状态标志
int flag = fcntl(fd, F_GETFL, 0);
switch (flag & O_ACCMODE)
{
case O_RDONLY:
printf("read only\n");
break;
case O_WRONLY:
printf("write only\n");
break;
case O_RDWR:
printf("read and write\n");
break;
default:
break;
}
if (flag & O_APPEND)
{
printf("append\n");
}
flag |= O_APPEND; // 追加flag
fcntl(fd, F_SETFL, flag); //设置文件状态标记
05. 目录相关操作(掌握)
5.1 getcwd函数
#include <unistd.h>
char *getcwd(char *buf, size_t size);
功能:获取当前进程的工作目录
参数:
buf : 缓冲区,存储当前的工作目录
size : 缓冲区大小
返回值:
成功:buf中保存当前进程工作目录位置
失败:NULL
5.2 chdir函数
#include <unistd.h>
int chdir(const char *path);
功能:修改当前进程(应用程序)的路径
参数:
path:切换的路径
返回值:
成功:0
失败:-1
5.3 opendir函数
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:
name:目录名
返回值:
成功:返回指向该目录结构体指针
失败:NULL
5.4 closedir函数
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭目录
参数:
dirp:opendir返回的指针
返回值:
成功:0
失败:-1
5.5 readdir函数
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取目录
参数:
dirp:opendir的返回值
返回值:
成功:目录结构体指针
失败:NULL
d_type文件类型说明:
取值 | 含义 |
---|---|
DT_BLK | 块设备 |
DT_CHR | 字符设备 |
DT_DIR | 目录 |
DT_LNK | 软链接 |
DT_FIFO | 管道 |
DT_REG | 普通文件 |
DT_SOCK | 套接字 |
DT_UNKNOWN | 未知 |
06. 时间相关函数
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
time_t mktime(struct tm *tm);
相关源代码:
open.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int fd = -1;
//1.以只读方式打开一个文件 如果文件不存在就报错
//fd = open("txt", O_RDONLY);
//2.以只写的方式打开一个文件 如果文件不存在就报错
//fd = open("txt", O_WRONLY);
//3.以只写的方式打开一个文件 如果文件不存在就创建, 如果文件存在就直接打开
//fd = open("txt", O_WRONLY | O_CREAT, 0644);
//4.以只读的方式打开一个文件 如果文件不存在就创建
//fd = open("txt", O_RDONLY | O_CREAT, 0644);
//5.以读写的方式打开文件 如果文件存在就报错, 如果文件不存在就创建
//fd = open("txt", O_RDWR | O_CREAT | O_EXCL, 0644);
//6.以读写的方式打开一个文件 如果文件不存在就创建 如果文件存在就清零
fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
printf("打开文件成功....\n");
return 0;
}
close.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#if 0
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
#endif
int main(void)
{
int fd = -1;
//1. 打开文件
fd = open("txt", O_RDWR | O_CREAT, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
printf("fd = %d\n", fd);
printf("打开文件成功....\n");
//2. 关闭文件 释放资源
close(fd);
return 0;
}
read.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 128
int main(void)
{
int fd = -1;
int ret = -1;
char buf[SIZE];
//1. 打开文件
fd = open("passwd", O_RDONLY);
if (-1 == fd)
{
perror("open");
goto err0;
}
printf("打开文件ok... fd: %d\n", fd);
//2. 循环读取数据
while(1)
{
memset(buf, 0, SIZE);
//每一次从文件中读取最多SIZE个字节
ret = read(fd, buf, SIZE - 1);
if (ret < 0)
{
perror("read");
break;
}
printf("%s", buf);
//读到文件结尾
if (ret < SIZE - 1)
{
break;
}
}
//3. 关闭文件
close(fd);
return 0;
err0:
return 1;
}
copy.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 128
//文件的简单拷贝 支持二进制
int main(int argc, char **argv)
{
int fdr = -1;
int fdw = -1;
int ret = -1;
char buf[SIZE];
//容错判断
if (3 != argc)
{
printf("usage: ./a.out filename1 filename2\n");
goto err0;
}
//1. 以只读的方式打开第一个文件
fdr = open(argv[1], O_RDONLY);
if (-1 == fdr)
{
perror("open");
goto err0;
}
//2. 以只写的方式打开第二个文件
fdw = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (-1 == fdw)
{
perror("open");
goto err1;
}
//3. 循环拷贝数据
while(1)
{
//从第一个文件中读取数据
memset(buf, 0, SIZE);
ret = read(fdr, buf, SIZE);
if (ret <= 0)
{
break;
}
//将读取的数据写入到第二个文件中
ret = write(fdw, buf, ret);
if (ret <= 0)
{
break;
}
}
//4. 关闭两个文件描述符
close(fdr);
close(fdw);
return 0;
err1:
close(fdr);
err0:
return 1;
}
unbock.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 128
int main(void)
{
int fd = -1;
int ret = -1;
char buf[SIZE];
//1. 打开一个终端设备 该设备默认是阻塞的
//fd = open("/dev/tty", O_RDWR);
fd = open("/dev/tty", O_RDWR | O_NONBLOCK);
if (-1 == fd)
{
perror("open");
goto err0;
}
//2. 读设备
memset(buf, 0, SIZE);
ret = read(fd, buf, SIZE);
if (ret <= 0)
{
perror("read");
}
printf("buf:%s\n", buf);
//3. 关闭文件
close(fd);
return 0;
err0:
return 1;
}
lseek.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 128
//以十六进制的方式查看文件内容
//deng@itcast:~/share/4th$ od -x txt
int main(void)
{
int fd = -1;
int ret = -1;
//1. 打开文件
fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (-1 == fd)
{
perror("open");
goto err1;
}
//在文件开头写七个字符
write(fd, "ABCDEFG", 7);
//将文件偏移30个字节
ret = lseek(fd, 1024 * 1024, SEEK_END);
if (-1 == ret)
{
perror("lseek");
goto err2;
}
write(fd, "123456789", 9);
//获取文件的大小
printf("file: %ld\n", lseek(fd, 0, SEEK_END));
//关闭文件
close(fd);
return 0;
err2:
close(fd);
err1:
return 1;
}
stat.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#if 0
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
* precision for the following timestamp fields.
* For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
#endif
//查看文件信息命令
//deng@itcast:~/share/4th$ stat txt
//获取文件相关信息
int main(void)
{
int ret = -1;
struct stat buf;
memset(&buf, 0, sizeof(buf));
//获取文件相关信息
ret = stat("txt", &buf);
if (-1 == ret)
{
perror("stat");
return 1;
}
printf("st_dev: %lu\n", buf.st_dev);
printf("st_ino: %lu\n", buf.st_ino);
printf("st_nlink: %lu\n", buf.st_nlink);
printf("st_uid: %d\n", buf.st_uid);
printf("st_gid: %d\n", buf.st_gid);
printf("st_rdev:%lu\n", buf.st_rdev);
printf("st_size: %ld\n", buf.st_size);
printf("st_blksize: %ld\n", buf.st_blksize);
printf("st_blocks: %ld\n", buf.st_blocks);
return 0;
}
stat1.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#if 0
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
* precision for the following timestamp fields.
* For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
#endif
//查看文件信息命令
//deng@itcast:~/share/4th$ stat txt
//获取文件相关信息
int main(int argc, char **argv)
{
int ret = -1;
struct stat buf;
if (2 != argc)
{
printf("usage: ./a.out filename\n");
return 1;
}
memset(&buf, 0, sizeof(buf));
//获取文件相关信息
ret = stat(argv[1], &buf);
if (-1 == ret)
{
perror("stat");
return 1;
}
printf("st_dev: %lu\n", buf.st_dev);
printf("st_ino: %lu\n", buf.st_ino);
printf("st_nlink: %lu\n", buf.st_nlink);
printf("st_uid: %d\n", buf.st_uid);
printf("st_gid: %d\n", buf.st_gid);
printf("st_rdev:%lu\n", buf.st_rdev);
printf("st_size: %ld\n", buf.st_size);
printf("st_blksize: %ld\n", buf.st_blksize);
printf("st_blocks: %ld\n", buf.st_blocks);
#if 0
switch((buf.st_mode & S_IFMT))
{
case S_IFSOCK:
printf("socket\n");
break;
case S_IFLNK :
printf("symbolic link\n");
break;
case S_IFREG :
printf("regular file\n");
break;
case S_IFBLK :
printf("block device\n");
break;
case S_IFDIR :
printf("directory\n");
break;
case S_IFCHR :
printf("character device\n");
break;
case S_IFIFO :
printf("FIFO\n");
break;
defalt:
printf("未知类型....\n");
}
#else
if (S_ISREG(buf.st_mode) )
printf("is it a regular file \n");
if (S_ISDIR(buf.st_mode) )
printf("directory \n");
if (S_ISCHR(buf.st_mode) )
printf("character device \n");
if (S_ISBLK(buf.st_mode) )
printf("block device \n");
if (S_ISFIFO(buf.st_mode))
printf("FIFO (named pipe) \n");
if (S_ISLNK(buf.st_mode) )
printf("symbolic link \n");
if (S_ISSOCK(buf.st_mode))
printf("socket \n");
#endif
//判断文件所属者权限
if (buf.st_mode & S_IRUSR)
printf("r");
else
printf("-");
buf.st_mode & S_IWUSR ? printf("w") : printf("-");
buf.st_mode & S_IXUSR ? printf("x") : printf("-");
//判断文件所属组权限
buf.st_mode & S_IRGRP ? printf("r") : printf("-");
buf.st_mode & S_IWGRP ? printf("w") : printf("-");
buf.st_mode & S_IXGRP ? printf("x") : printf("-");
//判断文件其它权限
buf.st_mode & S_IROTH ? printf("r") : printf("-");
buf.st_mode & S_IWOTH ? printf("w") : printf("-");
buf.st_mode & S_IXOTH ? printf("x") : printf("-");
printf("\n");
return 0;
}
access.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (2 != argc)
{
printf("usage: ./a.out filename\n");
return 1;
}
for (int i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
//判断文件是否存在
if (access(argv[1], F_OK) == 0)
{
printf("文件存在...\n");
}
else
{
printf("文件不存在....\n");
}
//判断文件是否有读的权限
if (access(argv[1], R_OK) == 0)
{
printf("可以读\n");
}
else
{
printf("不可以读\n");
}
return 0;
}
symlinc.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (3 != argc)
{
printf("usage: ./a.out filename1 filename2\n");
return 1;
}
//创建一个符号链接
if (-1 == symlink(argv[1], argv[2]))
{
perror("symlink");
return 1;
}
return 0;
}
dup.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//文件描述符复制
int main(void)
{
int fd = -1;
int newfd = -1;
//1. 打开文件
fd = open("txt", O_RDWR | O_CREAT, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
//2. 复制文件描述符
//newfd = dup(fd);
newfd = 10;
//如果newfd文件描述符已经与其它文件关联, 那么先close, 然后在使用该数字
newfd = dup2(fd, newfd);
if (-1 == newfd)
{
perror("dup");
return 1;
}
printf("fd : %d newfd: %d\n", fd, newfd);
//3. 关闭文件
close(fd);
close(newfd);
return 0;
}
dup2.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//文件描述符复制
int main(void)
{
int fd = -1;
int newfd = -1;
//1. 打开文件 Ctrl + P
fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
//2. 复制文件描述符
//newfd = dup(fd);
newfd = 10;
//如果newfd文件描述符已经与其它文件关联, 那么先close, 然后在使用该数字
newfd = dup2(fd, newfd);
if (-1 == newfd)
{
perror("dup");
return 1;
}
printf("fd : %d newfd: %d\n", fd, newfd);
write(fd, "123456789", 9);
write(newfd, "ABCDEFGHI", 9);
//3. 关闭文件
close(fd);
close(newfd);
return 0;
}
fcntl.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//文件描述符复制
int main(void)
{
int fd = -1;
int newfd = -1;
//1. 打开文件 Ctrl + P
fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
//2. 复制文件描述符 寻找一个大于或者等于10的最小的可以用文件描述符返回
newfd = fcntl(fd, F_DUPFD, 10);
if (-1 == newfd)
{
perror("fcntl");
return 1;
}
printf("fd : %d newfd: %d\n", fd, newfd);
write(fd, "123456789", 9);
write(newfd, "ABCDEFGHI", 9);
//3. 关闭文件
close(fd);
close(newfd);
return 0;
}
fcntl.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//文件描述符复制
int main(void)
{
int fd = -1;
int ret = -1;
//1. 打开文件 Ctrl + P
fd = open("txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (-1 == fd)
{
perror("open");
return 1;
}
//2. 获取文件状态标志
ret = fcntl(fd, F_GETFL);
if (-1 == ret)
{
perror("fcntl");
return 1;
}
if (ret & O_NONBLOCK)
{
printf("设置为非阻塞...\n");
}
else
{
printf("设置为阻塞...\n");
}
//设置为非阻塞
ret |= O_NONBLOCK;
ret = fcntl(fd, F_SETFL, ret);
if (-1 == ret)
{
perror("fcntl");
return 1;
}
//2. 获取文件状态标志
ret = fcntl(fd, F_GETFL);
if (-1 == ret)
{
perror("fcntl");
return 1;
}
if (ret & O_NONBLOCK)
{
printf("设置为非阻塞...\n");
}
else
{
printf("设置为阻塞...\n");
}
//3. 关闭文件
close(fd);
return 0;
}