文件描述符相关函数总结 dup2 dup

1、什么是文件描述符?        

        1、非负的整数。
        2、表示一个打开的文件。
        3、由系统调用(open)返回,被内核空间(后续系统调用)引用。
        4、内核缺省为每个进程打开三个文件描述符:

  • stdin 0 - 标准输入
  • stdout 1 - 标准输出
  • stderr 2 - 标准出错

这三个描述符也可以被修改 后面会讲

文件描述符的范围介于0到OPEN_MAX之间,传统Unix中OPEN_MAX宏被定义为63,现代Linux使用更大的上限。

2、文件描述符的打开关闭

#include <fcntl.h>

int open (//创建文件与读取文件 两项功能
    const char* pathname, // 路径
    int         flags,    // 模式
    mode_t      mode      // 权限(仅创建文件有效)
);

int open (
    const char* pathname, // 路径
    int         flags     // 模式
};  // 常用于读写文件

/*int creat (//创建文件 一项功能  一般用不到
    const char* pathname, // 路径
    mode_t      mode      // 权限
);  // 常用于创建文件*/

以上成功返回尽可能小的文件描述符,失败返回-1。

#include <unistd.h>

int close (
    int fd // 文件描述符
);//关闭文件描述符
成功返回0,失败返回-1。


flags为以下值的位或:

O_RDONLY   - 只读。\                   
O_WRONLY   - 只写。 > 只选一个        
O_RDWR     - 读写。 |
O_APPEND   - 追加。/

//当使用O_CREATE时 mode位参数才能被填写 如:0666
O_CREAT    - 创建,不存在即创建(已存在即直接打开,
             并保留原内容,除非...),
             有此位mode参数才有效。

//这俩是搭配O_CREAT的
O_EXCL     - 排斥,已存在即失败。\
                                  > 只选一个,
O_TRUNC    - 清空,已存在即清空  /  配合O_CREAT使用
             (有O_WRONLY/O_RDWR)。

这里就不得不说一下mod位的八进制权限码

  • mod位的权限由八进制表示
  • 系统可以用权限掩码屏蔽进程设置的部分权限
    0666 (rw-rw-rw-) & ~0022 = 0644 (rw-r--r--)(因为是八进制前面0不能省略 表示八进制)
  • 6=110 4=100 2=010 以此类推每一个八进制数对应三位二进制码
  • mod所设置的一共是三种用户的权限
    1-3位是属主权限
    4-6位是和属主同组人的权限
    7-9位是其他用户权限
    其实真实的权限前面还有一位代表文件格式分别是
     d 文件夹      | 链接     b 块设备文件     p管道文件
    ​​​   -  普通文件   c字符设备文件   s套接口文件
  • r 读  w写  x执行

3、文件读写

write


#include <unistd.h>
ssize_t write (
    int         fd,   // 文件描述符
    const void* buf,  // 缓冲区
    size_t      count // 期望写入的字节数  无符号
);
成功返回实际写入的字节数,失败返回-1。

read


#include <unistd.h>

ssize_t read (
    int    fd,   // 文件描述符
    void*  buf,  // 缓冲区
    size_t count // 期望读取的字节数
);
成功返回实际读取的字节数,失败返回-1

实现一个copy

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

int copy(const char *srcFileName,const char *destFileName){
	int sfd = open(srcFileName,O_RDONLY);
	if(sfd == -1){
		printf("%s\n",strerror(errno));
		return -1;
	}
	int dfd = open(destFileName,O_WRONLY|O_CREAT|O_EXCL,0644);
	if(dfd == -1){//access  stat   fstat
		if(errno == EEXIST){//该文件存在,是否要覆盖
			printf("%s 文件存在!\n",destFileName);
		}else{
			printf("%s\n",strerror(errno));
		}
		close(sfd);
		return -1;
	}
	char str[128] = {};
	ssize_t ret;
	while((ret = read(sfd,str,128))>0){
		write(dfd,str,ret);	
	}
	close(sfd);
	close(dfd);
	return 0;
}

//cp 
int main(int argc,char *argv[]){
	if(argc < 3){
		printf("%s srcfile destfile\n",argv[0]);
		return -1;
	}
	copy(argv[1],argv[2]);
	return 0;	
}

4、标准库IO

1、当系统调用函数被执行时,需要切换用户态和内核态,频繁调用会导致性能损失。

2、标准库做了必要的优化,内部维护一个缓冲区,只在满足特定条件时才将缓冲区与系统内核同步,借此降低执行系统调用的频率,减少进程在用户态和内核态之间来回切换的次数,提高运行性能。 (fread 和 read 的区别在于 read会调用指定大小的内存内容 但fread会调用比指定内容更多的内容 从而降低了切换时间)

#include <stdio.h>

int main () 
{
    FILE* fp = fopen ("stdio.dat", "wb");    
    if (! fp) 
    {
        perror ("fopen");
          return -1;
    }

    unsigned int i;
    for (i = 0; i < 100000; i++)
        fwrite (&i, sizeof (i), 1, fp);

    fclose (fp);

    return 0;
}

5、lseek

改变文件读取位置

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

//SEEK_SET   开头
//SEEK_CUR   当前
//SEEK_END   结尾
int main(){
	int fd1 = open("a.txt",O_WRONLY|O_APPEND);
	int fd2 = open("a.txt",O_WRONLY|O_APPEND);
	int fd3 = dup(fd1);

	lseek(fd1,0,SEEK_END); //末尾

	printf("%ld\n",lseek(fd1,0,SEEK_CUR));//返回位置
	printf("%ld\n",lseek(fd2,0,SEEK_CUR));
	printf("%ld\n",lseek(fd3,0,SEEK_CUR));
	
	char str[100] = "Hello wrold";
	write(fd1,str,strlen(str));//在末尾写入

	lseek(fd1,0,SEEK_END);
	lseek(fd2,0,SEEK_END);
	lseek(fd3,0,SEEK_END);
	
	printf("%ld\n",lseek(fd1,0,SEEK_CUR));
	printf("%ld\n",lseek(fd2,0,SEEK_CUR));
	printf("%ld\n",lseek(fd3,0,SEEK_CUR));
	return 0;	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值