dup() 和 dup2() 是两个非常有用的系统调用,都用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。
这个过程类似于现实生活中的配钥匙,钥匙相当文件描述符,锁相当于文件,本来一个钥匙开一把锁,相当于,通过旧的钥匙复制了一把新的钥匙,这样的话,旧的钥匙和新的钥匙都能开启这把锁。
对比于 dup(),dup2() 也一样,通过原来的文件描术符复制出一个新的文件描述符,这样的话,原来的文件描述符和新的文件描述符都指向同一个文件,我们操作两个文件描述符的任何一个,都能操作它所对应的文件.。
#include <unistd.h>
int dup(int oldfd) ;
功能:
通过 o1dfd 复制出一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终 o1dfd 和新的文件描述符都指向同一个文件。
参数:
o1dfd :需要复制的文件描述符 o1dfd
返回值:
成功: 新文件描述符
失败:-1
#include <unistd.h>
int dup2(int oldfd, int newfd);
功能:
通过 o1dfd 复制出一个新的文件描述符 newfd,如果成功,newfd 和函数返回值是同一个返回值,最终o1dfd 和新的文件描述符 newfd 都指向同一个文件
参数:
o1dfd :需要复制的文件描述符
newfd :新的文件描述符,这个描述符可以人为指定一个合法数字(0 1023),如果指定的数字已经被占用(和某个文件有关联),此函数会自动关闭 c1ose()断开这个数字和某个文件的关联,再来使用这个合法数字
返回值:
成功:返回 newfd
失败: 返回 -1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//dup dup2
int main(void)
{
int fd = -1;
int newfd = -1;
//1.打开文件
fd = open("test.txt",O_RDWR | O_CREAT,0644);
if (-1 == fd)
{
perror("open");
return 1;
}
printf("fd = %d\n",fd);
//文件描述符复制
// newfd = dup(fd);
newfd = 2;
// 如果文件描述符2已经跟某个文件关联,那么就先解除与该文件的关联,然后将该文件描述符与fd关联同一个文件
newfd = dup2(fd, newfd);
if (-1 == newfd)
{
perror("dup");
return 1;
}
printf("newfd = %d\n",newfd);
//2.操作
write(fd,"ABCDEFG",7);
write(newfd,"1234567",7);
//3,关闭文件描述符
close(fd);
close(newfd);
}
查看帮助文档
man fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd,int cmd, .../* arg */);
功能:改变已打开的文件性质,fcntl针对描述符提供控制。
参数
fd; 操作的文件描述符
cmd: 操作方式
arg: 针对cmd的值,fcntl能够接受第三个参数int arg。
返回值:
成功:返回某个其他值
失败:-1
fcntl函数有5种功能
//2,文件描述符复制
//功能等价于dup函数
//第三个参数0 表示返回一个最小的可用的文件描述符,并且大于或者等于0
newfd = fcntl(fd, F_DUPFD, 0);
if (-1 == newfd)
{
perror("fcntl");
return 1;
}
在原有状态行添加O_APPEND追加标记
//2,获取文件状态标记
int ret = fcntl(fd,F_GETFL);
if (-1 == ret)
{
perror("fcnti");
return 1;
}
if(ret & O_APPEND)
{
printf("before append\n");
}
else
{
printf("before not append\n");
}
//3,设置文件状态标记
ret = ret | O_APPEND ;
ret = fcnlt(fd,F_SETFL, ret);
if (-1 == ret)
{
perror("fcnti");
return 1;
}
#include <unistd.h>
char *getcwd(char *buf,size t size);
功能:获取当前进程的工作目录
参数:
buf : 缓冲区,存储当前的工作目录
size : 缓冲区大小
返回值:
成功: buf中保存当前进程工作目录位置
失败: NULL
#include <unistd.h>
int chdir(const char *path);
功能: 修改当前进程(应用程序)的路径
参数
path: 切换的路径
返回值:
成功:0
失败:-1
注意,即使可以修改,但是用pwd打印,路径还是原来,没有改变
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define SIZE 32
//getcwd chdir
int main(void)
{
int ret = -1;
char buf[SIZE];
//1,获取当前进程的工作目录
memset(buf, 0, SIZE);
if (NULL == getcwd(buf, SIZE))
{
perror("getcwd");
return 1;
}
printf("buf:%s\n", buf);
//2,改变当前进程的工作目录
ret = chdir("/home/deng");
if (-1 == ret)
{
perror("chdir");
return 1;
}
//3,获取当前进程的工作目录
memset(buf, 0, SIZE);
if (NULL == getcwd(buf,SIZE))
{
printf("buf:%s\n", buf);
}
}
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:
name: 目录名
返回值:
成功:返回指向该目录结构体指针
失败: NULL
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭目录
参数:
dirp: opendir返回的指针
返回值:
成功: 0
失败: -1
#include <stdio.h>
#include <string.h>
#include <stdlib,h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
//目录打开和关闭
int main(void)
{
DIR *dir = NULL;
//1,打开目录
dir = opendir("test");
if (NULL == dir)
{
perror("opendir");
return 1;
}
printf("打开目录成功...,\n");
//2,关闭目录
closedir(dir);
return 0;
}
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取目录
参数:
dirp: opendir的返回值
返回值:
成功:目录结构体指针
失败: NULL
结构体说明:
struct dirent
{
ino_t d_ino; // 此目录进入点的inode
off_t d_off; // 目录文件开头至此目录进入点的位移
signed short int d_reclen; // d_name 的长度,不包含NULL 字符
unsigned char d_type; // d_type 所指的文件类型
char d_name[256]; // 文件名
}
d_type文件类型说明:
取值 | 含义 |
---|---|
DT_BLK | 块设备 |
DT_CHR | 字符设备 |
DT_DIR | 目录 |
DT_LNK | 软链接 |
DT_FIFO | 管道 |
DT_REG | 普通文件 |
DT_SOCK | 套接字 |
DT_UNKNOWN | 未知 |
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
int main()
{
//目录打开和关闭
DIR *dir = NULL;
struct dirent *d = NULL;
//1,打开目录
dir = opendir("/usr/local/cpp_demo");
if (NULL == dir)
{
perror("opendir");
return 1;
}
printf("打开目录成功.... \n");
//2。循环读取目录内密
while(1)
{
//读取目录的内容
d = readdir(dir);
if (NULL == d)
{
perror("readdir");
break;
}
printf(" d name:%s , type: ",d->d_name);
//判断文件类型
switch(d->d_type)
{
case DT_BLK:
printf("央设备");
break;
case DT_CHR:
printf("字符设备");
break;
case DT_DIR:
printf("目录");
break;
case DT_FIFO:
printf("管道");
break;
case DT_LNK :
printf("符号链接");
break;
case DT_REG:
printf("普通文件");
break;
case DT_SOCK:
printf("套接字");
break;
default:
printf("未知文件类型");
}
printf("\n");
}
//3,关闭目录
closedir(dir);
}