用户态与内核态 & 文件流与文件描述符 简介【转】
转自:https://www.cnblogs.com/Jimmy1988/p/7479856.html
用户态和内核态
程序代码的依赖和调用关系如下图所示:
- Lib:标准ASCI C函数,几乎所有的平台都支持该库函数,因此依赖该库的程序可移植性好;
- System Function:系统调用函数,与系统内核进行交互,不同平台具备不同的函数接口,因此可移植性较差
区分用户态和内核态主要是由于系统资源的有限性,不能无限制的随意分配给用户使用,必须由系统进行统一管理
- User mode:不能直接对系统资源进行访问,如果要操作系统资源,必须转化为内核态
- Kernel mode:管理系统资源,可直接对系统资源进行控制和访问
内核为用户提供了统一的API供其使用,不同的系统的API接口不同,为了便于代码的移植,出台了POSIX标准,类Unix系统(Unix、Linux、BSD、SunOS等)均支持该标准。
文件流与文件描述符
问题:
由上图我们可看到,每执行一次系统调用,都要涉及到CPU状态的切换,即从用户态切换到内核态,即从用户空间切换到内核空间,实现上下文切换的过程,会消耗相当一部分的CPU资源,因此频繁的磁盘访问对程序的执行效率将造成很大影响。解决方案:
为了解决以上的难题,采用了缓冲区
的概念,当对磁盘文件进行操作时,可一次性从磁盘文件中读出大量的数据暂放到缓冲区中,以后对这部分数据的访问就不需要再进行系统调用了;当对文件行操作后,可将处理后的数据暂存到输出缓冲区,待文件缓冲区满后,一次性写入到磁盘。
以上,数据的输入输出就像是水在流动一样,因此我们采用了流
的概念。
文件流 :
简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向;
文件流用结构体表示:struct FILE
.
FILE的结构体又是怎么样的呢?我们可以进行查找一下:[niesh@niesh ~]$ vim /usr/include/stdio.h
我们看到了 stdio.h
的文件中有一行:
__BEGIN_NAMESPACE_STD
/* The opaque type of streams. This is the definition used elsewhere. */
typedef struct _IO_FILE FILE;
__END_NAMESPACE_STD
显然,FILE
是 _IO_FILE
的类型替换,那么我们找一下 _IO_FILE
在哪里呢?
[niesh@niesh ~]$ grep -rn "\<_IO_FILE\>" /usr/include/
/usr/include/c++/4.8.2/streambuf:178: * This is based on _IO_FILE, just reordered to be more consistent,
/usr/include/libio.h:145:struct _IO_jump_t; struct _IO_FILE;
/usr/include/libio.h:163: struct _IO_FILE *_sbuf;
/usr/include/libio.h:246:struct _IO_FILE { //此处正解
/usr/include/libio.h:267: struct _IO_FILE *_chain;
/usr/include/libio.h:291: struct _IO_FILE _file;
/usr/include/libio.h:299: struct _IO_FILE *_freeres_list;
/usr/include/libio.h:316:typedef struct _IO_FILE _IO_FILE;
/usr/include/libio.h:325:#define _IO_stdin ((_IO_FILE*)(&_IO_2_1_stdin_))
/usr/include/libio.h:326:#define _IO_stdout ((_IO_FILE*)(&_IO_2_1_stdout_))
/usr/include/libio.h:327:#define _IO_stderr ((_IO_FILE*)(&_IO_2_1_stderr_))
/usr/include/libio.h:329:extern _IO_FILE *_IO_stdin attribute_hidden;
/usr/include/libio.h:330:extern _IO_FILE *_IO_stdout attribute_hidden;
/usr/include/libio.h:331:extern _IO_FILE *_IO_stderr attribute_hidden;
/usr/include/libio.h:391:extern int __underflow (_IO_FILE *);
/usr/include/libio.h:392:extern int __uflow (_IO_FILE *);
/usr/include/libio.h:393:extern int __overflow (_IO_FILE *, int);
/usr/include/libio.h:395:extern _IO_wint_t __wunderflow (_IO_FILE *);
/usr/include/libio.h:396:extern _IO_wint_t __wuflow (_IO_FILE *);
/usr/include/libio.h:397:extern _IO_wint_t __woverflow (_IO_FILE *, _IO_wint_t);
/usr/include/libio.h:435:extern int _IO_getc (_IO_FILE *__fp);
/usr/include/libio.h:436:extern int _IO_putc (int __c, _IO_FILE *__fp);
/usr/include/libio.h:437:extern int _IO_feof (_IO_FILE *__fp) __THROW;
/usr/include/libio.h:438:extern int _IO_ferror (_IO_FILE *__fp) __THROW;
/usr/include/libio.h:440:extern int _IO_peekc_locked (_IO_FILE *__fp);
/usr/include/libio.h:446:extern void _IO_flockfile (_IO_FILE *) __THROW;
/usr/include/libio.h:447:extern void _IO_funlockfile (_IO_FILE *) __THROW;
/usr/include/libio.h:448:extern int _IO_ftrylockfile (_IO_FILE *) __THROW;
/usr/include/libio.h:465:extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
/usr/include/libio.h:467:extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
/usr/include/libio.h:469:extern _IO_ssize_t _IO_padn (_IO_FILE *, int, _IO_ssize_t);
/usr/include/libio.h:470:extern _IO_size_t _IO_sgetn (_IO_FILE *, void *, _IO_size_t);
/usr/include/libio.h:472:extern _IO_off64_t _IO_seekoff (_IO_FILE *, _IO_off64_t, int, int);
/usr/include/libio.h:473:extern _IO_off64_t _IO_seekpos (_IO_FILE *, _IO_off64_t, int);
/usr/include/libio.h:475:extern void _IO_free_backup_area (_IO_FILE *) __THROW;
/usr/include/libio.h:478:extern _IO_wint_t _IO_getwc (_IO_FILE *__fp);
/usr/include/libio.h:479:extern _IO_wint_t _IO_putwc (wchar_t __wc, _IO_FILE *__fp);
/usr/include/libio.h:480:extern int _IO_fwide (_IO_FILE *__fp, int __mode) __THROW;
/usr/include/libio.h:514:extern int _IO_vfwscanf (_IO_FILE * __restrict, const wchar_t * __restrict,
/usr/include/libio.h:516:extern int _IO_vfwprintf (_IO_FILE *__restrict, const wchar_t *__restrict,
/usr/include/libio.h:518:extern _IO_ssize_t _IO_wpadn (_IO_FILE *, wint_t, _IO_ssize_t);
/usr/include/libio.h:519:extern void _IO_free_wbackup_area (_IO_FILE *) __THROW;
/usr/include/stdio.h:44:struct _IO_FILE;
/usr/include/stdio.h:48:typedef struct _IO_FILE FILE;
/usr/include/stdio.h:64:typedef struct _IO_FILE __FILE;
/usr/include/stdio.h:168:extern struct _IO_FILE *stdin; /* Standard input stream. */
/usr/include/stdio.h:169:extern struct _IO_FILE *stdout; /* Standard output stream. */
/usr/include/stdio.h:170:extern struct _IO_FILE *stderr; /* Standard error output stream. */
(⊙o⊙)…,还挺多啊,不过仔细观察,发现只有 libio.h
的246行是对该结构体的定义,我们打开瞅瞅!
[niesh@niesh ~]$ vim /usr/include/libio.h
struct FILE
的结构体成员如下代码所示:
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
文件描述符:
每个进程,当打开一个文件后,内核会为其建立一个打开文件的数组 (数组的前三个为stdin,stdout,stderr),然后返回打开文件位于数组的索引值(下标),该所以只即为文件描述符,只要文件不关闭,用户便可以根据该描述符对文件进行访问和操作。不同点:
文件描述符:表示为int类型的对象:如stdin对应文件描述符0,stdout对应文件描述符1;
流:表示为指向结构FILE的指针FILE* ,因此流也称为文件指针
若需要对特定设备进行控制操作,必须使用文件描述符方式,没有函数能对流进行这类操作
如果需要按照特殊的方式进行I/O操作(例如非阻塞的方式),必须使用文件描述符方式,也没有函数能对流进行这类操作。联系:
流给用户程序提供了更高一级的(功能更强大,使用更简化)的I/O接口,它处在文件描述符方式的上层,也就是说,流函数是通过文件描述符函数来实现的。
用户态与内核态 & 文件流与文件描述符 简介【转】的更多相关文章
- 用户态与内核态 & 文件流与文件描述符 简介
用户态和内核态 程序代码的依赖和调用关系如下图所示: Lib:标准ASCI C函数,几乎所有的平台都支持该库函数,因此依赖该库的程序可移植性好: System Function:系统调用函数,与系统内 ...
- 【Linux 系统】Linux探秘之用户态与内核态
一. Unix/Linux的体系架构 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核).内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程 ...
- (转)linux用户态和内核态理解
原文:https://blog.csdn.net/buptapple/article/details/21454167 Linux探秘之用户态与内核态-----------https://www.cn ...
- Linux 用户态与内核态的交互【转载】
Linux 用户态与内核态的交互 在 Linux 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字实现的,例如iprote2网络管理工具,它与内核的交 ...
- linux 用户态和内核态以及进程上下文、中断上下文 内核空间用户空间理解
1.特权级 Intel x86架构的cpu一共有0-4四个特权级,0级最高,3级最低,ARM架构也有不同的特权级,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查.硬件已经提 ...
- cpu的用户态和内核态和内存的用户空间内核空间
谈到CPU的这两个工作状态,也就是处理器的这两个工作状态,那我们有必要说一下为什么搞出这两个鬼玩意出来. 用过电脑的娃娃们肯定知道在一个系统中既有操作系统的程序,也由普通用户的程序.但那么 ...
- 【APUE】用户态与内核态的区别
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态).此时处理器处于特权级最高的(0级)内核代码中 执行.当进程处于内核态时,执行的内核代码会使用当前进程 ...
- Linux用户态与内核态通信的几种方式
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Linux 用 ...
- linux用户态和内核态理解
1.特权级 Intel x86架构的cpu一共有0-4四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查.硬件已经提供了一套特权级使用的相关机制 ...
随机推荐
- IO模型介绍
先理解几个问题: (1)为什么读取文件的时候,需要用户进程通过系统调用内核完成(系统不能自己调用内核)什么是用户态和内核态?为什么要区分内核态和用户态呢? 在 CPU 的所有指令中,有些指令是非常危险 ...
- Carthage下没有Build文件夹
问题描述: 用Carthage管理项目时,执行Carthage upate --platform iOS后发现Carthage目录下没有Build文件夹 解决方案: 在Xcode > Prefe ...
- day06(深浅拷贝,元组,字典,集合)
1,今日内容: 1.深浅拷贝:**** 2.元组 - 元组可以存放可变类型 *** 3.字典:***** -- 增删改查 -- 常用方法 4.集合:** -- 集合运算 5.数据类型的相互转化 *** ...
- Linux程序前台后台切换
1.在Linux终端运行命令的时候,在命令末尾加上 & 符号,就可以让程序在后台运行 root@Ubuntu$ ./tcpserv01 & 2.如果程序正在前台运行,可以使用 Ctrl ...
- mongodb解决只能本地连接不能远程连接问题
本机windows7 ,装了vagrant盒子,并在盒子上装了mongodb服务,本机连接虚拟机时连不上. 解决方法: 修改虚拟机上 mongodb.conf 文件,将bind_ip = 127.0. ...
- C博客作业01--分支、顺序结构
1.本章学习总结 1.1 思维导图 1.2 本章学习体会及代码量学习体会 1.2.1 学习体会 在暑假已经有初步接触c语言,所以在学习c语言的开始会比较轻松,但仍然解题时候步骤太过于繁琐,简单的题目复 ...
- Wiki leaks files backup
Wiki leaks files backup 来源 http://ftp.icm.edu.pl/packages/incoming/torrent/ Index of /packages/inco ...
- 题解:YNOI/GZOI2019 与或和
题目大意: 1. 求所有的子矩阵的and之和2. 求所有子矩阵的or之和 由于是位运算,那么久直接拆位,于是就变成了求全0子矩阵的个数和全1子矩阵的个数那么题目就变成了简单的单调栈问题 #includ ...
- postgreSQL可视化工具pgAdmin3 导入表结构和数据
材料:.backup文件.postgreSQL(pgAdmin3) 1.新建一个数据库2.选中数据库右键还原,弹出框中选择本地计算机备份文件路径---->点击还原(选择一个修改时间最早和最晚的还 ...
- JSP中EL很常用,怎样使用大于号、小于号、等于号等
JSP中EL很常用,怎样使用大于号.小于号.等于号等 符号 在EL中使用 常规 1 等于 eq == 2 不等于 ne != 3 大于 gt > 4 小于 lt < 5 大于等于 ge ...