用户态和内核态

程序代码的依赖和调用关系如下图所示:

  • 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接口,它处在文件描述符方式的上层,也就是说,流函数是通过文件描述符函数来实现的。

用户态与内核态 & 文件流与文件描述符 简介的更多相关文章

  1. 用户态与内核态 & 文件流与文件描述符 简介【转】

    转自:https://www.cnblogs.com/Jimmy1988/p/7479856.html 用户态和内核态 程序代码的依赖和调用关系如下图所示: Lib:标准ASCI C函数,几乎所有的平 ...

  2. 【Linux 系统】Linux探秘之用户态与内核态

    一. Unix/Linux的体系架构 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核).内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程 ...

  3. (转)linux用户态和内核态理解

    原文:https://blog.csdn.net/buptapple/article/details/21454167 Linux探秘之用户态与内核态-----------https://www.cn ...

  4. Linux 用户态与内核态的交互【转载】

    Linux 用户态与内核态的交互  在 Linux 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字实现的,例如iprote2网络管理工具,它与内核的交 ...

  5. linux 用户态和内核态以及进程上下文、中断上下文 内核空间用户空间理解

    1.特权级         Intel x86架构的cpu一共有0-4四个特权级,0级最高,3级最低,ARM架构也有不同的特权级,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查.硬件已经提 ...

  6. cpu的用户态和内核态和内存的用户空间内核空间

    谈到CPU的这两个工作状态,也就是处理器的这两个工作状态,那我们有必要说一下为什么搞出这两个鬼玩意出来.       用过电脑的娃娃们肯定知道在一个系统中既有操作系统的程序,也由普通用户的程序.但那么 ...

  7. 【APUE】用户态与内核态的区别

    当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态).此时处理器处于特权级最高的(0级)内核代码中 执行.当进程处于内核态时,执行的内核代码会使用当前进程 ...

  8. Linux用户态与内核态通信的几种方式

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Linux 用 ...

  9. linux用户态和内核态理解

    1.特权级         Intel x86架构的cpu一共有0-4四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查.硬件已经提供了一套特权级使用的相关机制 ...

随机推荐

  1. 1 Introduction

    1. Introduction 1.1. License Flowable is distributed under the Apache V2 license. 1.2. Download http ...

  2. css清除默认样式,stylus学习

    reset.css html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, ...

  3. Android艺术——探究Handler运行机制

    我们从开发的角度来说,Handler是Android 的消息机制的上层接口.说到Handler,大家都会说:哦,Handler这个我知道干什么的,更新UI.没错,Handler的确是用于更新UI的,具 ...

  4. ABP中的拦截器之AuditingInterceptor

    在上面两篇介绍了ABP中的ValidationInterceptor之后,我们今天来看看ABP中定义的另外一种Interceptor即为AuditingInterceptor,顾名思义就是一种审计相关 ...

  5. js对象取值的两种方式

    :"李四"}; var v1 = obj.name1; //张三, 使用点的方式 //报错,不能使用点的方式 ]; //李四,使用中括号的方式 var key = "na ...

  6. JS-JAVASCRIPT的eval()方法

    Lodop的传统模版是JS语句,如果储存的这种JS模版,可用javascript的eval()方法获取,该方法属于JS的范畴,并不是lodop语句,由于这个方法很多程序员可能不常用,对于这个JS方法不 ...

  7. 洛谷P3806 点分治

    点分治 第一次写点分治..感觉是一个神奇而又暴力的东西orz 点分治大概就是用来处理树上链的信息,把路径分成过点x和不过点x的两种,不过点x的路径可以变成过点x的子树中一点的路径,递归处理 #incl ...

  8. 【BZOJ5506】[GXOI/GZOI2019]旅行者(最短路)

    [BZOJ5506][GXOI/GZOI2019]旅行者(最短路) 题面 BZOJ 洛谷 题解 正着做一遍\(dij\)求出最短路径以及从谁转移过来的,反过来做一遍,如果两个点不由同一个点转移过来就更 ...

  9. Linux交换分区使用过多的处理办法

    处理办法 echo "vm.swappiness=0" >>/etc/sysctl.conf sysctl -p swapoff -a && swapo ...

  10. Meterpreter提权详解

      0x01 Meterpreter自动提权 1.生成后门程序 我们在kali的命令行下直接执行以下命令获得一个针对windows的反弹型木马: msfvenom -p windows/meterpr ...