【深入理解计算机系统】系统级I/O

输入/输出(I/O)是在主存和外部设备(例如磁盘驱动器、终端和网络)之间复制数据的过程。输入操作是从I/O设备复制数据到主存,输出操作是从主存复制数据到I/O设备。

在Linux系统中,通过使用由内核提供的系统级Unix I/O函数来实现较高级别的I/O函数。

Unix I/O

一个Linux文件就是一个m个字节的序列,所有I/O设备(例如网络、磁盘和终端)都被模型化为文件,而所有输入和输出都被当作对相应文件的读和写来执行。这中将设备优雅的映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,简称Unix I/O, 这使得所有的输入和输出都能以一种统一且一致的方式来执行:

  1. 打开文件。一个应用程序通过要求内核打开相应的文件,来告诉它想要访问的I/O设备。内核返回一个小的非负整数,叫做描述符,它在后续对此文间的所有操作中标识这个文件。内核记录有关这个打开文件的所有信息。应用程序只需要记住这个描述符。
  2. Linux shell 创建的每个进程开始时都由三个打开的文件:标准输入、标准输出和标准错误。
  3. 改变当前的文件位置。对于每个打开文件,内核保持着一个文件位置k,初始为0。即从文件开头起始的字节编偏移量。
  4. 读写文件。一个读操作就时从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增加到k+n。当超过文件字节大小时,读操作会出发一个end-of-file的条件,应用程序能检测到这个条件。同理,写操作就时从内存复制n个字节到一个文件中。
  5. 关闭文件。当应用完成对文件的访问之后,它就通知内核关闭文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述父回复到可用的描述符池中。无论一个进程因为何种原因终止时,内核都会关闭所有打开的文件并释放他们的内存资源。

文件

每个Linux文件都有一个类型(type)来表明它在系统中的角色:

  1. 普通文件
  2. 目录(directory),包含一组链接文件,每个链接都将医生文件名映射到一个文件,这个文件可能时目录。每个目录至少含有两个条目:”.”是该目录自身的链接,以及“..”是到目录层次结构中父目录的链接。下图是window下,使用vim命令打开的一个目录
  3. 嵌套字(socket)用来与另一个进程进行跨网络通信的文件
    其他文件类型包含命名通道(named pipe)、符号链接(symbol link),以及字符和块设备(character and block device)。

在使用读、写文件的时候,使用read和write传送的字节比应用程序要求的要少,这些不足值(short count)不表示有错误,出现这样的情况原因有:

  1. 读时遇到EOF: 假设我们准备读一个文件,该文件从当前文件位置开始值含有20多个字节,而我们以50个字节的片段进行读取。这样返回不足值为20,此后read将通过返回不足值0来发出EOF信号。
  2. 从终端读取文本行。如果打开文件是与终端相关联的,那么每个read函数将一次传送一个文本行,返回的不足值等于文本行大小。
  3. 读和写网络套接字,如果打开的文件对应于网络套接子,那么内部缓冲约束和较长的网络延迟会引起read和write返回不足值。

如果想创建健壮Web服务器这样的网络应用,就必须通过反复调用read和write处理不足值,知道所需要的字节都传送完毕。

RIO 包健壮地读写

称为 Robust I/O,它会自动处理文件读写时的不足值。RIO提供了两类不同的函数:

  1. 无缓冲的输入输出函数,直接在内存和文件之间传送数据,没有应用级缓冲。它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。
  2. 带缓冲的输入函数,这些函数允许你高效地从文件中读取文本和二进制数据,着些文件的内容缓存在应用级缓冲区内,类似于为printf这样的标准I/O函数提供的缓冲区。

C语言定义了一组高级输入函数,称为标准I/O库,为程序员提供了Unix I/O的较高级别的替代。

网络I/O

在Internet 网中,客户端和服务器通过在连接上发送和接收字节流来通信。从连接一对进程的意义上而言,连接是点对点的。从数据可以同时双向流动的角度来说,它是全双工的。并且从由源进程发出的字节流最终被目的进程以它发出的顺序收到它的角度来说,它也是可靠的。

一个套接字是连接的一个端点。每个套接字都有相应的套接字地址,是由一个Internet地址和一个16位的整数端口组成。当客户端发起一个请求时,客户端套接字中的端口时由内核自动分配的,称为临时端口。服务器套接字地址中的端口通常时某个知名端口,一个特定的服务与该端口进行关联。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2280端口映射到公网,发现经常被暴力破解,自己写了个临时封禁ip功能的脚本,实现5分钟内同一个ip登录密码错误10次就封禁这个ip5分钟,并且进行邮件通知使用步骤openwrt为19.07.03版本,其他版本没有测试过安装bashmsmtpopkg
#!/bin/bashcommand1&command2&wait从Shell脚本并行运行多个程序–杨河老李(kviccn.github.io)
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/phpls-ls 2.编辑修改.bash_profile文件(没有.bash_profile文件的情况下回自动创建)sudovim~/.bash_profile在文件的最后输入以下信息,然后保存退出exportPATH="/Applications/MAMP/bin/php/php7.2.20/b
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如zh_CN之类的语言包,进行中文语言包装:apt-getinstalllanguage-pack-zh-hans3、安装好后我们可以进行临时修改:然后添加中文支持: locale-genzh_CN.UTF-8临时修改> export LC_ALL='zh_CN.utf8'> locale永久
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexadecimalbash2#[0~1]0[0~7]0x[0~f]or0X[0~f]perl0b[0~1]0[0~7]0x[0~f]tcl0b[0~1]0o[0~7]0x[0~f]bashdifferentbaserepresntationreference2.StringlengthLanguageStr
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全命令补全方法:yum-yinstallbash-completionsource/usr/share/bash-completion/bash_completionsource<(kubectlcompletionbash)echo"source<(kubectlcompletionbash)">>~/.bashrc 
参考这里启动jar包shell脚本修改过来的#!/bin/bash#默认应用名称defaultAppName='./gadmin'appName=''if[[$1&&$1!=0]]thenappName=$1elseappName=$defaultAppNamefiecho">>>>>>本次重启的应用:$appName<
#一个数字的行#!/bin/bashwhilereadlinedon=`echo$line|sed's/[^0-9]//g'|wc-L`if[$n-eq1]thenecho$linefidone<1.txt#日志切割归档#!/bin/bashcd/data/logslog=1.logmv_log(){[-f$1]&&mv$1$2
#文件增加内容#!/bin/bashn=0cat1.txt|whilereadlinedon=[$n+1]if[$n-eq5]thenecho$lineecho-e"#Thisisatestfile.\n#Testinsertlineintothisfile."elseecho$linefidone#备份/etc目录#
# su - oraclesu: /usr/bin/ksh: No such file or directory根据报错信息:显示无法找到文件 /usr/bin/ksh果然没有该文件,但是发现存在文件/bin/ksh,于是创建了一个软连接,可以规避问题,可以成功切换到用户下,但无法执行系统自带命令。$. .bash_profile-ksh: .: .b
history显示历史指令记录内容,下达历史纪录中的指令主要的使用方法如果你想禁用history,可以将HISTSIZE设置为0:#exportHISTSIZE=0使用HISTIGNORE忽略历史中的特定命令下面的例子,将忽略pwd、ls、ls-ltr等命令:#exportHISTIGNORE=”pwd:ls:ls-ltr:”使用HIS
一.命令历史  1.history环境变量:    HISTSIZE:输出的命令历史条数,如history的记录数    HISTFILESIZE:~/.bash_history保存的命令历史记录数    HISTFILLE:历史记录的文件路径    HISTCONTROL:     ignorespace:忽略以空格开头的命令
之前在网上看到很多师傅们总结的linux反弹shell的一些方法,为了更熟练的去运用这些技术,于是自己花精力查了很多资料去理解这些命令的含义,将研究的成果记录在这里,所谓的反弹shell,指的是我们在自己的机器上开启监听,然后在被攻击者的机器上发送连接请求去连接我们的机器,将被攻击者的she
BashOne-LinersExplained,PartI:Workingwithfileshttps://catonmat.net/bash-one-liners-explained-part-oneBashOne-LinersExplained,PartII:Workingwithstringshttps://catonmat.net/bash-one-liners-explained-part-twoBashOne-LinersExplained,PartII
Shell中变量的作用域:在当前Shell会话中使用,全局变量。在函数内部使用,局部变量。可以在其他Shell会话中使用,环境变量。局部变量:默认情况下函数内的变量也是全局变量#!/bin/bashfunctionfunc(){a=99}funcecho$a输出>>99为了让全局变量变成局部变量
1、多命令顺序执行;  命令1;命令2  多个命令顺序执行,命令之间没有任何逻辑联系&&  命令1&&命令2  逻辑与,当命令1正确执行,才会执行命令2||  命令1||命令2  逻辑或,当命令1执行不正确,才会执行命令2例如:ls;date;cd/home/lsx;pwd;who ddif=输入文件of=输
原博文使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗?首先,这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang"。Linux执行文件时发现这个格式,会把!后的内容提取出来拼接在脚本文件或路径之前,当作实际执行的命令。 Shebang这个符号通常在Unix系统的脚本
1、历史命令history[选项][历史命令保存文件]选项:-c:  清空历史命令-w:  把缓存中的历史命令写入历史命令保存文件 ~/.bash_historyvim/etc/profile中的Histsize可改存储历史命令数量历史命令的调用使用上、下箭头调用以前的历史命令使用“!n”重复执行第n条历史
目录1.Shell脚本规范2.Shell脚本执行3.Shell脚本变量3.1环境变量3.1.1自定义环境变量3.1.2显示与取消环境变量3.1.3环境变量初始化与对应文件的生效顺序3.2普通变量3.2.1定义本地变量3.2.2shell调用变量3.2.3grep调用变量3.2.4awk调用变量3.3
   http://www.voidcn.com/blog/wszzdanm/article/p-6145895.html命令功能:显示登录用户的信息命令格式:常用选项:举例:w显示已经登录的用户及正在进行的操作[root@localhost~]#w 11:22:01up4days,21:22, 3users, loadaverage:0.00,0.00,0.00USER