linux文件基础-3_原子操作_文件共享_dup_dup2_fcntl

1、原子操作

1)原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch。
2)每种操作系统中都有一些机制来实现原子操作,以保证那些需要原子操作的任务可以运行。

3)O_APPEND实现接续写
(1)我们在同一个进程中两次打开同一个文件,分别读取的结果为两种
①第一种:fd1和fd2分别读
②第二种:接续读
不加O_APPEND,结果为fd1和fd2分别读。

(2)分别读的原因
①fd1和fd2所对应的文件指针是不同的独立指针
②文件指针是包含在动态文件的文件管理表,linux系统的进程中不同的fd对应独立的文件管理表。

(3)open时加O_APPEND标志实现接续写
①2个fd拥有不同的文件指针,只考虑自己的移位
②O_APPEND标志将独立的文件指针关联起来
③O_APPEND对文件指针的影响,对文件的读写是原子的

2、文件共享

1)文件共享:同一个文件被多个独立读写体同时操作。
2)文件共享的意义:文件共享实现多线程同时操作同一个大文件,以减少文件读写时间,提升效率。
3)文件共享的3中方式
①第一种:同一进程多次open文件
②第二种:在不同进程中open文件(fd可以一样)
③第三种:dup和dup2两个API来让进程复制文件描述符。

3、文件描述符细节

1)文件描述符本质为数字,进程表中文件描述符表的表项,通过查表得到文件指针->这个文件对应的文件表
2)fd的分配是操作系统内部自动分配的,规定fd从0开始增加,也是有最大限制。
3)linux文件描述符表是个数组(不是链表),fd是index,文件表指针是value。
4)fd中的0、1、2已经默认被系统占用了,对应stdin、stdout、stderr,对应标准输入、标准输出、标准错误。
5)标准输入对应键盘设备,标准输出对应lcd等显示器设备。
6)printf对应到标准输出stdout,stdio有一个函数叫fpirntf,可以指定输出到哪个文件描述符中。

4、文件描述符的复制dup和dup2

include <unistd.h>

int dup(int oldfd)
int dup2(int oldfd, int newfd)

1)dup对fd复制,返回值为新的描述符,但是不能设置fd的,分配原则遵守fd分配原则
2)dup返回的fd和原来的fd都指向打开的动态文件,构成共享文件,同时写入是接续写。
3)dup2系统调用修复了dup缺陷,能指定分配的新的文件描述符的数字

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FILENAME    "1.txt"

int main(void)
{
    int fd1 = -1, fd2 = -1, fd3 = -1;
    fd1 = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
    if (fd1 < 0)
    {
        perror("open");
        return -1;
    }
    printf("fd1 = %d.\n", fd1);
    close(1);       // 1就是标准输出stdout
    // 复制文件描述符
    fd2 = dup(fd1);     // fd2一定等于1,因为前面刚刚关闭了1,这句话就把
    // 1.txt文件和标准输出就绑定起来了,所以以后输出到标准输出的信息就
    // 可以到1.txt中查看了。
    printf("fd2 = %d.\n", fd2);
    printf("this is for test");
    
    // 测试dup2
    fd3 = dup2(fd1, 16);
    printf("fd2 = %d.\n", fd3);
    
    close(fd1);
    return -1;
}

4)命令行中的重定位命令 >
(1)linux中shell执行命令(ls pwd…)后的打印->默认进入到stdout.
(2)使用>可以将ls、pwd等命令的输出给重定位到一个文件
(3)>的实现,利用的是open+close+dup,关闭stdout,dup将打开文件和fd=1关联起来。

ls -l > list.txt  
将执行“ls -l” 命令的结果写入文件list.txt中。

5、fcntl

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

1)fcntl函数是一个多功能文件管理的工具箱,2个参数和1个变参。
(1)fd是文件
(2)cmd是命令
(3)变参,配合cmd

2)F_DUPFD这个cmd的作用是复制文件描述符(类似于dup、dup2)
(1)从可用的文件描述符中找一个>=arg的数字作为复制的文件描述符
(2)与dup2返回值不同,dup2返回指定的fd,否则报错。F_DUPFD命令返回的是>=arg的最小的那一个数字

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FILENAME	"1.txt"

int main(void)
{
	int fd1 = -1, fd2 = -1;
	
	fd1 = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd1 < 0)
	{
		perror("open");
		return -1;
	}
	printf("fd1 = %d.\n", fd1);
	
	close(1);  
	
	fd2 = fcntl(fd1, F_DUPFD, 0);
	printf("fd2 = %d.\n", fd2);

    // 测试写
	while (1)
	{
		write(fd1, "aa", 2);
		sleep(1);
		write(fd2, "bb", 2);
	}

	close(fd1);
	return -1;
}

注:笔记整理,参考于朱有鹏老师的嵌入式核心课程


被抛弃的写随笔公众号改写技术文章了,感兴趣的可以关注公众号:王崇卫
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值