Linux学习笔记-文件IO

区别之------c语言的 文件操作函数(标准IO?)

C语言---文件操作及文件操作函数详解_c语言文件操作函数_羟基与苯的博客-CSDN博客[C语言]文件操作函数_c语言打开文件的函数_衡一兄的博客-CSDN博客

 笔记来源:

11-系统编程阶段说再前面的话_哔哩哔哩_bilibili11-系统编程阶段说再前面的话是黑马程序员-Linux系统编程的第47集视频,该合集共计184集,视频收藏或关注UP主,及时了解更多相关视频内容。icon-default.png?t=N7T8https://www.bilibili.com/video/BV1KE411q7ee?p=47&vd_source=f443c8140671d1c361aa817ad1193312什么是Linux系统编程?_哔哩哔哩_bilibili什么是Linux系统编程?是【北京迅为】嵌入式学习之Linux系统编程篇的第1集视频,该合集共计31集,视频收藏或关注UP主,及时了解更多相关视频内容。icon-default.png?t=N7T8https://www.bilibili.com/video/BV1zV411e7Cy?p=1&vd_source=f443c8140671d1c361aa817ad1193312

概念辨析

系统调用概念

系统调用:内核提供的函数:由操作系统实现并提供给外部应用程序的(为数不多的)编程接口,是应用程序同操作系统之间交互数据的桥梁。

小区别:为了保证系统的安全性,linux手册 manPage中的系统调用都是对系统调用的一次浅封装,比如open()对应的是sys_open()。因此如果概念想稍微有所区别的话,可以给封装后的调用叫做系统函数。大体上可以混为一谈。就是 操作系统实现并提供给外部应用程序的编程接口。

系统调用和库调用(函数) 两者概念区别:

Linux || 文件描述符 系统调用与库函数_linux系统调用和库函数_布鲁克要补钙的博客-CSDN博客

库函数我们写程序一直在使用,非常多。

文件(系统)IO和标准IO概念,和两者区别

标准IO与系统IO的区别_系统io和标准io的区别-CSDN博客

Linux中的系统IO与标准IO_标准io和系统io的区别-CSDN博客

系统IO的特点
  1. 系统IO的操作的对象是文件描述符。标准IO的对象是文件指针。
  2. 系统IO并不带缓冲,因此每次对系统IO的操作都视为数据与内核相交互。
  3. 某些场合下,只能使用系统IO。例如:处理socket的时候,只能使用系统IO,标准IO不行

个人对两对概念的理解

系统IO

open

//头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>     //包含 flags的宏

//上面三个头文件相当于:
#include <unistd.h>    //包含 open函数


// 两个open:第二个open多一个参数,是指定新建不存在文件的权限
int open(const char* pathname, int flags);
int open(const char* pathname, int flags, mode_t mode);	

**入参**:
入参 mode,是一个8进制整型,指定打开不存在文件的权限,只有当参2指定了CREAT才有用。如 0777 (第一个0表示8进制)
ps:创建文件时,指定文件访问权限,权限同时受umask影响:文件权限=mode&(~umask)

入参 flags,打开文件时带的读写权限:
O_RDONLY
O_WRONLY
O_RDWR    //读写
O_APPEND  //追加属性
O_CREAT   //创建属性
O_EXCL
O_TRUNC  //截断文件大小(清空)
O_NONBLOCK

**返回值**
一个int,文件描述符;打开失败返回-1并设置,errno,一个操作系统的环境变量,可以直接去查看它的值。

即 ~umask == 775

 open的示例:
#include <fcntl.h>
#include <stdio.h>
#include <error.h> //error的头文件
#include <unistd.h>
#include <string.h>//strerror()的头文件

int main(int argc,char* argv[]){
	int fd1=0;
	int fd2=0;

	fd1=open("./dirt.txt",O_RDONLY|O_CREAT|O_TRUNC,0644);
    /*打开的文件不存在*/
	fd2=open("./dirt2.txt",O_RDONLY);

	printf("fd1=%d\n",fd1);
    
    //errno,打开失败会被写值;strerror函数可以解析它的值,以得知打开失败的原因。
	printf("fd2=%d,errno=%d:%s\n",fd2,errno,strerror(errno));

	close(fd1);
	close(fd2);
	return 0;
}

close

//头文件
#include <unistd.h>

int close(int fd)

//入参:
open返回的整型文件描述符

//返回值:
成功返回 0;失败 -1;
隐式回收:

实际上,当进程运行结束时, 所有该进程打开的文件会被关闭, 申请的内存空间会被释放, 系统的这一特性称为隐式回收系统资源。但是有时候不能保证进程能即使运行结束,因此手动加close比较保险。

read

打开一个文件后,要对文件进行操作了。 read即把数据读出来到buffer

#include <unistd.h>
ssize_t read(int fd, void* buf, size_t count); //ssize_t的第一个s表示 有符号

//参3是缓冲区的大小

//成功返回实际读到的字节数,返回0时意味着读到了文件末尾,失败返回-1并设置errno
(*重点)read返回值分析

write

#include <unistd.h>
ssize_t write(int fd, const void* buf, size_t count); 

//3参注意和read的3参区别开,这个是实际要写入的内容的大小,而非源buffer 的大小

//成功返回实际写入的字节数, 失败返回-1, 并设置errno

open/close/write/read 小练习--实现cp命令:

//mycp.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

const int BS = 1024;//读到的数据放到buffer里面,buffer开栈最大1M

int main(int argc, char* argv[]) {
	if (argc != 3) {
		printf("format: ./mycp a b\n");
		exit(1);
	}
	int fd1 = open(argv[1], O_RDONLY);
	int fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd1 == -1 || fd2 == -1) {
		perror("open error");
		exit(1);
	}
	char buf[BS];
	ssize_t s;
    
    //读一个buffer写一个buffer
	while ((s = read(fd1, buf, BS)) > 0) {
		ssize_t ret = write(fd2, buf, s);
		if (ret != s) {
			perror("write error");
			exit(1);
		}
	}
	if (s < 0) {
		perror("read error");
		exit(1);
	}
	close(fd1);
	close(fd2);
	return 0;
}

了解小机制:

(1)系统调用和库函数比较:库函数具有预读入和缓输出机制

fgetc()、fputc() 的实际读写过程----函数内部实现不是真的是字节级别的操作(用户态->内核态->驱动磁盘),是存在读入和写出缓冲的。

  了解小机制:标准IO,Unbuffered IO是什么?

标准IO (有偷懒的)ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准IO库处理很多细节。例如缓存分配,以优化长度执行IO等。

Unbuffered IO (无偷懒的)无缓冲IO。不带缓存指的是,每个read,write都调用内核中的一个系统调用。

标准IO和Unbuffered IO使用的函数:

标准IOUnbuffered IO
打开fopenopen
fread ,fgetc,fgetsread
fwrite,fputc, fputswrite
操作位置fseek,ftell,rewindlseek
关闭fcloseclose
两者关系 :                                                                                                                                                                   Unbuffered IO (无偷懒的)的意义:                                                                                    1、我们知道Linux的传统是Everything is a file, IO函数不仅用于读写常规文件,也用于读写设备,比如终端或网络设备。在读写设备时通常是不希望有缓冲的,例如向代表网络设备的文件写数据就是希望数据通过网络设备发送出去,而不希望只写到缓冲区里就算完事儿了,当网络设备接收到数据时应用程序也希望第一时间被通知到,所以网络编程通常直接调用Unbuffered IO函数。

也就是说:
如果进程A 和 进程B打开同一文件,如果采用系统IO,进程A写到内核I/O缓冲区中的数据从进程B也能及时读到,而标准库的I/O缓冲区则不具有这一特性。

————————————————
原文链接:https://blog.csdn.net/w903414/article/details/109340230

(2)OS内核绝不会让你逐字节的向Disk上写数据,实际上它维护了一个系统级缓冲,只有当从用户空间过来的数据在该缓冲上写满时,他才会一次性将数据冲刷到Disk上。如下图右侧内核区方框。

(3)当使用系统调用的方法时,要不断的在用户空间和内核空间进行来回切换,这会消耗大量时间。

【Linux】标准IO,Unbuffered IO,文件描述符_unbufferedio-CSDN博客

案例:使用 fgetc()&fputc()   与   使用 read()&write()字节级buffer读写   ,分别实现cp功能, 通过对比cp相同大文件的cp时间,了解 fgetc()、fputc() 的内部机制。

总结:内核缓冲区处理的是内核空间和磁盘之间的数据传递,目的是减少访问磁盘的次数;而用户缓冲区处理的是用户空间和内核空间的数据传递,目的是减少系统调用的次数

一文搞懂用户缓冲区与内核缓冲区-CSDN博客常常听到有程序员会跟你讨论:“我们在读写文件的时候,系统是有缓存的”。但实际上有一部分人把用户进程缓存区和系统空间缓存区的概念混淆了,包括这两种缓冲区的用法和所要解决的问题,还有其它类似的概念。本文就来区分一下不同的缓冲区概念(主要针对类unix平台)。  用户进程和操作系统的关系,首先我用一张图来解释“用户进程和操作系统的关系:这是一个计算机系统运行时的简化模型,我们把所有运行在操作系统上的进程成为用户进程,它们都运行在用户空间(可以看到用户空间有很多进程)。把操作系统运行的空间成为系统空.https://blog.csdn.net/Jiangtagong/article/details/108703123?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169761635116800180636638%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169761635116800180636638&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-108703123-null-null.142%5Ev96%5Epc_search_result_base7&utm_term=%E6%96%87%E4%BB%B6%20%E5%86%85%E6%A0%B8%E7%BC%93%E5%86%B2%E5%8C%BA&spm=1018.2226.3001.4187

虎牙一面:请详细介绍一下内核缓冲区_Java入门到如风的博客-CSDN博客写这篇文章的起因主要是最近复习计网滑动窗口中看到的一句话 “窗口的本质是内核缓冲区”,之前一直没有仔细去理解,以为就是缓存,很多博客写得也是缓存…,But 缓冲和缓存在概念上其实是有区别的,本文就来详细介绍一下内核缓冲区先来回顾下内核态和用户态:众所周知,CPU 上会运行两种程序,一种是操作系统的内核程序(也称为系统程序),一种是应用程序。前者完成系统任务,后者实现应用任务。两者之间有控制和被控制的关系,前者有权管理和分配资源,而后者只能向系统申请使用资源。显然,我们应该把在 CPU 上运行的这两类程序加以_内核缓冲区https://blog.csdn.net/m110572/article/details/125236240?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169716423116800213041563%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169716423116800213041563&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-125236240-null-null.142%5Ev96%5Epc_search_result_base7&utm_term=%E5%86%85%E6%A0%B8%E7%BC%93%E5%86%B2%E5%8C%BA&spm=1018.2226.3001.4187

系统IO时发生阻塞

从IO read 文件时是否会发生阻塞等待,文件分为两种属性

常规性文件(无论数据大小,数据是现成的):

阻塞性文件(即/dev目录下,管道、设备、网络设备文件,比如显示/输入等终端设备,tty文件):因为存在数据暂时还没来的可能性

 Demo:体验读文件发生阻塞

这个程序读了标准输入文件,然后写到标准输出。执行这个程序后,程序开始阻塞,等待屏幕输入。

直到屏幕有输入,回车。屏幕回显刚才的输入。

思考:为什么程序执行到read那里,就停住了?谁导致的?

(1)文件应该带着一个表示其是否阻塞的属性;

(2)read函数有针对读阻塞性文件的机制,去等待,而不是去返错。

下面通过open函数重新打开标准输入文件,并把它的性质改为非阻塞,然后进行读写

//echo-nonblock.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

const int BS = 128;

int main(int argc, char* argv[]) {
	int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
	if (fd < 0) {
		perror("open /dev/tty error");
		exit(1);
	}
	char buf[BS];
	memset(buf, 0, BS);
	ssize_t n;
	while ((n = read(fd, buf, BS)) < 0) {
		if (errno != EWOULDBLOCK) {
			perror("read /dev/tty error");
			exit(1);
		} else {
			printf("didn't get input, try again\n");
			sleep(1);
		}
	}
	write(STDOUT_FILENO, buf, n);
	close(fd);
	return 0;
}

小说明:read函数返回-1,并且errno=EAGAINEWOULDBLOCK,说明不是read失败,而是read在以非阻塞方式读一个设备文件网络文件,没读到数据

阻塞方式存在的问题也正是后来网络IO中selectpollepoll函数存在的原因

fcntl函数

fcntl函数:改变一个已经打开文件的访问控制属性(之前学习:open函数可以设置新建文件的访问控制权限)

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

将fd设置为非阻塞模式的核心调用:

int flags=fcntl(fd, F_GETFL);
flags|= O_NONBLOCK;//通过或运算,在文件状态flsgs上加上非阻塞属性
int ret=fcntl(fd, F_SETLF, flags);

lseek函数

:修改 文件偏移量属性 的系统IO函数

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

//参数:
offset:偏移量 (字节)
whence:起始偏移位置(SEEK_SET | SEEK_CUR |SEEK_END)

//返回:
成功:从SEEK_SET的偏移量
失败:-1 error

IO读写 使用同一偏移位置:

如下:新write一个文件内容,紧跟着read,什么也read不到。

修改: 如上,将被注释的lseek放开。手动归零读写指针位置。

小技巧-用lseek获取文件大小:

lseek(fd, 0, SEEK_END);

注意:lseek只负责偏移读写位置指针,返回值是偏移量,不一定是真正文件大小。要想使文

件大小真正拓展, 必须引起IO操作

//lseek-extend-file.c
int main(int argc,char* argv[]){
	int fd=open(argv[1],O_RDWR);
	if(fd==-1){
		perror("open error");
		exit(1);
	}
	/*从文件的结束位置开始,向后偏移110*/
	int size=lseek(fd,110,SEEK_END);
	printf("The file's size:%d\n",size);
	/*然后写入一个空字符*/
	write(fd,"\0",1);
	close(fd);
	return 0;
}

小技巧-用ftruncate函数扩展文件大小:(注意文件要有 写权限)

stat/lstat函数

作用:获取文件属性(从inode中获取);

#include <sys/types.h>
#include <sys/stat.h>  //注意头文件需要单独加
#include <unistd.h>

int stat(const char* pathname, struct stat* statbuf);
入参:文件路径、查询结果传出
返回值:成功返回0, 失败返回-1并设置errno

/*传出参数:结构体信息(基本就是ll查出来的东西)*/
struct stat {
	dev_t     st_dev;         /* ID of device containing file */
	ino_t     st_ino;         /* Inode number */
	mode_t    st_mode;        /* File type and mode */
	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;     /* Block size 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
};

使用demo-利用stat获取文件大小:属性:

//stat-get-file-size.c
int main(int argc, char* argv[]) {
	struct stat st;
	int ret = stat(argv[1], &st);	//忽略了错误处理
	printf("%s size = %ld\n", argv[1], st.st_size);
	return 0;
}

注意:stat穿透: 当用stat获取软连接的文件属性时, 会穿透符号连接直接返回软连接指向的本尊的文件属性, vim, cat等命令也有穿透作用(打开软连接文件,内容不是一个路径,而是文件内容本尊)

解决方法:lstat函数(函数用法完全一样,就函数名前面加个l)

ps: readlink -f 软链接文件,该命令可以实现查看软链接真实文件内容,即 目标绝对路径。

14 软硬链接-CSDN博客文章目录文件系统inode软硬链接软连接硬链接软硬链接的区别总结文件系统文件=属性+内容在Linux中,一般把属性数据集合在一起,取名为inode,而内容则保存在block中。一般一个文件只有一个inode,但有多个数据块block。但是硬盘当中有多个文件,所以就会有多个inode和block,操作系统会将这些inode管理起来,形成inode表。所以文件系统其实是分区的整体化描述,比如基本情况,空间一共多大,inode,block等信息。所以使用ls -l的时候看到的除了看到文件名,还看https://blog.csdn.net/qq_52670477/article/details/120811134?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%9F%A5%E7%9C%8B%E8%BD%AF%E8%BF%9E%E6%8E%A5%E6%96%87%E4%BB%B6%E7%9A%84%E5%86%85%E5%AE%B9&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-120811134.142%5Ev96%5Epc_search_result_base7&spm=1018.2226.3001.4187

link和unlink函数

之前了解了创建硬链接的命令

ln makefile makefile.hard:为makefile创建硬连接

现在学习创建和删除硬链接的函数

link函数:用来创建硬链接的,结合inode知识,实质上就是为已经存在的文件创建目录项dentry

int link(const char *oldpath, const char *newpath);

用法demo-使用linkunlink函数实现mv命令::

mv//移动文件位置或者重命名
int main(int argc, char* argv[]) {
	int ret = link(argv[1], argv[2]);
	if (ret == -1) {
		perror("link error");
		exit(1);
	}

	ret = unlink(argv[1]);
	if (ret == -1) {
		perror("unlink error");
		exit(1);
	}
	return 0;
}

unlink函数的特征: 清除文件时, 如果文件的硬连接计数减到了0, 没有dentry与之对应, 但该文件仍不会马上被释放掉. 要等到所有打开该文件的进程关闭该文件, 系统才会择机将文件彻底释放。

一个demo验证:

//unlink-demo.c
int main(int argc, char* argv[]) {
	int fd = 0;
	int ret = 0;
	char* p = "test of unlink\n";
	char* p2 = "after write something\n";

	fd = open("temp.txt", O_RDWR | O_TRUNC | O_CREAT, 0644);
	if (fd < 0)
		perr_exit("open file error");

	ret = write(fd, p, strlen(p));
	if (ret == -1)
		perr_exit("write error");

	printf("hello,I'm printf\n");
	ret = write(fd, p2, strlen(p2));
	if (ret == -1)
		perr_exit("write error");

	printf("Entry key to continue\n");
	p[3] = 'a';
	getchar();
	close(fd);

	ret = unlink("temp.txt");
	if (ret == -1)
		perr_exit("unlink error");

	return 0;
}

但是如果在unlink之前诱发段错误, 程序崩溃, temp.txt就会存活下来. 所以将unlink这一步放到打开文件之后紧接着就unlink掉

虽然文件被unlink掉了,进程还在运行中,用户用cat查看不到磁盘上的对应文件, 但是write函数拿到fd写文件仍可正常写入。
————————————————
原文链接:https://blog.csdn.net/DanielSYC/article/details/118458055

目录操作

目录也是文件,可以用vim打开目录内容:目录的文件内容 是 目录项和inode

目录权限rwx实际意义

目录操作函数 (opendir readdir closedir   ---类似于文件操作函数     --位于man手册第3卷,实际上是库函数

#include <dirent.h>
DIR* opendir(const char* name);	/*返回的是一个目录结构体指针*/
int closedir(DIR* dirp);

struct dirent* readdir(DIR* dirp);//dirctory entry

//目录文件下,实际上不仅包括名字和目录项
struct dirent {
	ino_t          d_ino;       /* Inode number */
	off_t          d_off;       /* Not an offset; see below */
	unsigned short d_reclen;    /* Length of this record */
	unsigned char  d_type;      /* Type of file; not supported by all filesystem types */
	char           d_name[256]; /* Null-terminated filename */
};

用目录操作函数实现ls的功能:

//readdir-myls.c
int main(int argc, char* argv[]) {
	DIR* dirp = opendir(argv[1]);	//忽略了错误处理
	struct dirent* sdp;
	while ((sdp = readdir(dirp)) != NULL) {//隐藏目录项中的 .和..
		if (strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0) {
			continue;
		} else {
			printf("%s\n", sdp->d_name);
		}
	}
	closedir(dirp);
	return 0;
}

从功能上,可以 比ls多一点小功能。可以传参,不仅能打开当前目录,也可以打开传入的目录 

无非 ls 是不传参,写死打开当前目录

*章节练习 -实现 ls-R:递归显示目录

个人思路:参照myls,打开并读取(opendir、readddir)目录,可以得到一级目录项。一级目录项中有文件也有目录。我们需要识别目录,并进一步打开(stat获取文件类型)。

关键是递归的实现。

// 针对目录,执行打开/读取/解析目录项的操作
void fetchdir(const char* dir){
	char name[PATH_LEN];
	struct dirent* sdp;
	DIR* dp;
	/*打开目录失败*/
	if((dp=opendir(dir))==NULL){
		fprintf(stderr,"fetchdir:can't open %s\n",dir);
		return;
	}
	/*循环读取内容*/
	while((sdp=readdir(dp))!=NULL){
        /*遇到当前目录和上一级目录,跳过,否则会陷入死循环*/
		if((strcmp(sdp->d_name,".")==0)||(strcmp(sdp->d_name,"..")==0))
			continue;
		/*路径名是否越界*/
		if(strlen(dir)+strlen(sdp->d_name)+2>sizeof(name)){
			fprintf(stderr,"fetchdir:name %s %s is too long\n",dir,sdp->d_name);
		}else{
            /*拼接为一个路径,传给isFile函数*/
			sprintf(name,"%s/%s",dir,sdp->d_name);
			isFile(name);
		}
	}
	closedir(dp);
}

//判断如果是普通文件,则直接打印;如果是目录,执行打开/读取/递归的操作
void isFile(char* name){
	struct stat sbuf;
    /*获取文件属性失败*/
	if(stat(name,&sbuf)==-1){
		fprintf(stderr,"isFile:can't access %s\n",name);
		exit(1);
	}
    /*这是一个目录文件:调用函数fetchdir*/
	if((sbuf.st_mode&S_IFMT)==S_IFDIR){
		fetchdir(name,isFile);
	}
    /*不是目录文件:是一个普通文件,打印文件信息*/
	printf("%ld\t\t%s\n",sbuf.st_size,name);
}

int main(int argc,char* argv[]){
	/*不指定命令行参数*/
	if(argc==1)
		isFile(".");
	else{ //用户给了不止一个参数
		while(--argc>0)
			isFile(*++argv);
	}
	return 0;
}

dup/dup2函数

duplicate:复制, 副本

cat makefile > m1:将cat的结果重定向到m1(此时m1与makefile内容相同)

cat makefile >> m1:将cat的结果重定向并追加到m1后面(此时m1是双份的makefile)

CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/113981796

【Linux】文件操作/文件描述符/重定向/缓冲区_野猪佩奇`的博客-CSDN博客 文件基础知识、文件操作、文件描述符、重定向理解、Linux 下一切皆文件理解以及缓冲区理解。https://blog.csdn.net/m0_62391199/article/details/128600173?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%96%87%E4%BB%B6%20%E5%86%85%E6%A0%B8%E7%BC%93%E5%86%B2%E5%8C%BA&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-128600173.142%5Ev96%5Epc_search_result_base7&spm=1018.2226.3001.4187

The dup() system call creates a copy of the file descriptor oldfd, using the lowest-numbered unused file descriptor for the new descriptor.

dup作用:实现了,对oldfd的文件,再新增一个文件描述符指向它。两个文件描述符指向同一个文件。

#include <unistd.h>
int dup(int oldfd); //返回新的文件描述符。新的文件描述符文件是旧的的副本

dup2

作用:把 newfd指向的文件指针改成 oldfd 的。这样针对 newfd的读写操作,实际生效都是针对 oldfd

int dup2(int oldfd, int newfd);
//返回值:执行成功,返回 newfd

参考:

Linux系统编程学习笔记_find列出软连接_Daniel_187的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值