Linux系统编程

文件与I/O

  • C标准I/O库函数与Unbuffered I/O函数

    • C标准I/O库函数printf()、putchar()、fputs(),会在用户空间开辟I/O缓冲区
    • 系统函数open()、read()、write()、close()等位于C标准库的I/O缓冲区的底层,也称为无缓冲I\O(Unbuffered I/O)函数
    • 读写常规文件时调用标准库I/O比Unbuffered I/O要快,且不需自己管理I/O缓冲区
    • 读写终端或网络设备等不需要缓冲区,通常直接调用Unbuffered I/O
    • 每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的信息,称为进程描述符(Process Descriptor)
    • task_struct中有一个指针指向files_struct结构体,称为文件描述表,其中每个表项包含一个指向已打开的文件的指针
    • 用户不能直接访问内核中的文件描述表,而只能使用文件描述符表的索引(0、1、2等),称为文件描述符,用int型变量保存
    • 调用open打开一个文件时,内核分配一个文件描述符并返回给用户程序,该文件描述符表项中的指针指向新打开的文件
    • 读写文件时,用户程序把文件描述符传给read或write,内核根据文件描述符找到相应的表项,再通过表项中的指针找到相应文件
    • 程序启动时会自动打开三个文件:标准输入、标准输出和标准错误输出
  • open/close
    • int open(const char *pathname, int flags, ... );
    • 文件权限由open的mode参数和当前进程的umask掩码共同决定
    • int close(int fd);
  • read/write
    • 阻塞(Block):进程调用一个阻塞的函数时,该进程被置于睡眠(Sleep)状态,这是内核调度其他程序进行,直到该进程等待的事件发生了(如网络上接收到数据包)才有可能继续运行
    • 运行(Running):正在被执行或就绪状态(随时都可执行)
    • 轮询(Poll):本来应该阻塞在这里但事实上没有阻塞,而是直接返回错误,调用者应试着再读一次
    • 非阻塞I/O有个缺点,如果所有设备都一直没有数据到达,调用者需要反复查询做无用功,如果阻塞在那里,操作系统可以调度别的进程执行
    • 使用非阻塞I/O时,通常不会在一个while循环中不停查询,而是没延迟议会来查询一下,在延迟等待的时候可以调度其他进程执行,但这样的缺点是有数据到达时可能不能及时处理
    • select(2)函数可以阻塞地同时监视多个设备,还可以设定阻塞等待的超时时间
  • lseek
    • 移动当前读写位置(偏移量)
  • fcntl
    • 文件状态属性(File Status Flag):当前进程如何访问设备或文件,如读、写、追加、非阻塞等
    • 重新设置一个已打开的文件的状态属性,而不必重新open文件
    • Shell重定向语法:在<、>、>>、<>前添加一个数字,该数字就表示在哪个文件描述符上打开文件
    • $ command > /dev/null 2>&1:将命令command的标准输出重定向到/dev/null,然后将该命令可能产生的错误信息(标准错误输出)也重定向到和标准输出(&1,不加&会被解释成文件名)相同的文件,即/dev/null
    • 写在/dev/null文件中的数据不会被显示,即执行命令但不打印正常或错误信息
  • ioctl
    • 传送控制信息,文件或设备本身的属性,如串口波特率、终端窗口大小等
    • read/write读写的数据,是I/O操作的主体,称为in-band数据;不能用read/write读写的数据,称为Out-of-band数据
  • mmap
    • 把磁盘文件的一部分直接映射到内存,对文件的读写可直接用指针而不需通过read/write函数

文件系统

  • 引言

    • 如何呈现给用户一个树状目录结构?如何处理用户的文件和目录操作请求?
    • 如何让树状目录结构实现在磁盘上的线性存储?怎样设计文件系统的存储格式使访问磁盘的效率最高?
    • 各种文件和目录操作在磁盘上的实际效果是什么?
  • ext2文件系统
    • 文件系统中最小的单位是块(Block),ext2文件系统将整个分区划分成若干个同样大小的块组(Block Group),每个块组都由以下部分组成:

      • 超级块(Super Block):描述正而过分区的文件系统信息,如块大小、文件系统版本号
      • 块组描述符表(GDT,Group Descriptor Table):存储一个块组的描述信息,如从哪里开始是inode表,从哪里开始是数据块等。整个分区分成多少个块组就对应有多少个块组描述符
      • 块位图(Block Bitmap):描述整个块组中哪些块已用哪些块空闲
      • inode位图(inode Bitmap):和块位图类似,本身占一个块,其中每个bit表示一个inode是否空闲
      • inode表(inode Table):存储文件的描述信息,如文件类型、权限、大小、创建/修改/访问时间等,即ls -l命令看到的那些信息
      • 数据块:存储文件数据
    • 磁盘的最小读写单位称为扇区(Sector),通常是512字节
    • 数据块寻址
    • 文件和目录操作的系统函数:
      • stat(2):读取文件的inode
      • access(2)
      • chmod(2)
      • chown(2)
      • utime(2)
      • truncate(2)
      • link(2)
      • rename(2)
      • mkdir(2)
      • rmdir(2)
  • 虚拟文件系统(VFS,Virtual File System):Linux内核在各种不同的文件格式之上做了一个抽象层,使得文件、目录、读写访问等概念称为抽象层的概念,因此各种文件系统看起来和用起来都一样
    • Linux的文件系统:网络文件系统、磁盘文件系统、特殊文件系统等
    • VFS作为一个通用文件系统,抽象了文件系统的四个基本概念,文件、目录项、索引节点、挂载点
    • 在Linux中除进程外一切皆是文件
    • VFS的四个基本对象
      • 超级块对象(superblock object):一个已安装的文件系统
      • 索引节点对象(inode object):一个文件
      • 目录项对象(dentry object):一个目录
      • 文件对象(file object):由进程打开文件

    • 每个进程在PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指针,指向内核中的file结构体
    • file结构体成员
      • f_flags:File Status Flag
      • f_pos:当前读写位置
      • f_count:引用计数(Reference Count)
    • 每个file结构体指向一个file_operations结构体,这个结构体成员都是函数指针,指向实现各种文件操作的内核函数
    • 每个file结构体都有一个指向dentry(directory entry 目录项)结构体的指针,内核在dentry cache中缓存了目录的树状结构,每个节点是一个dentry结构体,可根据路径(如/home/akaedu/a)找到文件的inode
    • inode结构体保存着从磁盘分区的inode上读来的信息,如所有者、文件大小、类型、权限等
    • 每个inode结构体都有一个指向inode_operations结构体的指针,后者是一组函数指针指向一些完成文件目录操作的内核函数,如添加删除文件和目录、跟踪符号链接等
    • inode结构体有一个指向super_block结构体的指针,后者保存着从磁盘分区的超级块上读来的信息,如文件系统类型,块大小等,其s_root成员是一个指向dentry的指针,表示这个文件系统的根目录被mount到哪里
    • dup和dup2可用来复制一个现存的文件描述符,使这两个文件描述符指向同一个file结构体
    • 硬链接(hard link):一个inode号对应多个文件名,即一个文件使用了多个别名
    • 软链接(soft link):一个inode号对应一个文件名,普通文件

进程

  • 引言

    • 每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux的PCB是task_struct结构体,主要包括以下信息

      • 进程id:一个非负整数,系统中每个进程有唯一的id
      • 进程的状态:运行、挂起、停止、僵尸等
      • 进程切换时需要保存和恢复的一些CPU寄存器
      • 描述虚拟地址空间的信息
      • 描述控制终端的信息
      • 当前工作目录
      • umask掩码
      • 文件描述符表,包含很多指向file结构体的指针
      • 和信号相关的信息
      • 用户id和组id
      • 控制终端、Session和进程组
      • 进程可以使用的资源上限(Resource Limit)
    • fork:根据一个现有的进程(父进程 Parent Process)复制出一个新的进程(子进程 Child Process)
    • exec:执行新的程序

  • 环境变量

    • PATH:可执行文件的搜索路径,可包含多个目录,用:隔开,通过echo命令查看值
    • SHELL:当前Shell,值通常是/bin/bash
    • TERM:当前终端类型
    • LANG:语言和locale,决定字符编码及时间、货币等信息的显示格式
    • HOME:当前用户主目录的路径
  • 进程控制
    • fork:系统调用函数,调用后进入内核,根据父进程复制出一个子进程。调用一次,返回两次(父进程调用一次,父进程和子进程中各返回一次)
    • gdb只能跟踪一个进程(默认是父进程),而不能同时跟踪多个进程
    • exec:用fork创建子进程后,子进程需要调用exec以执行另一个程序
    • wait和waitpid:进程终止是Shell(父进程)调用wait或waitpid得到它的退出状态同时彻底删除这个进程,若进程终止后但父进程未调用wait或waitpid对它进行清理,这是的进程状态为僵尸进程
  • 进程间通信
    • 每个进程各自有不同的用户地址空间,看不到其他进程的全局变量,进程间要交换数据必须通过内核
    • 在内核中开辟一块缓冲区,进程1把数据从用户空间拷贝到缓冲区,进程2再从内核缓冲区把数据读走,这种机制称为进程间通信(IPC,InterProcess Communication)
    • 管道是一种最基本的IPC机制,由pipe函数创建,有以下限制
      • 两个进程通过一个管道只能实现单向通信,如果是子进程写父进程读,需要开另一个管道
      • 管道的读写端通过打开文件描述符传递,需通过fork传递文件描述符
    • 管道的4种特殊情况
      • 所有指向管道写端的文件描述符都关闭了
      • 有指向管道写端的文件描述符没关闭
      • 所有指向管道读端的文件描述符都关闭了
      • 有指向管道读端的文件描述符没关闭
    • 其他IPC机制:FIFO、Unix Domain Socket(目前使用最广泛),利用文件系统中的特殊文件来标识IPC通道

Shell脚本

  • 如何执行命令

    • 解释执行用户的命令,输入一条,解释执行一条,执行方式有交互式(Interactive)和批处理(Batch)(用户事先写一个Shell脚本(Script),Shell一次执行完)两种
    • 用户在命令行输入命令后,Shell会fork并exec该命令,但内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程  
  • 基本语法
    • 变量:由大写字母加下划线组成,分环境变量和本地变量(只存在于当前Shell进程)
    • 文件名代换(Globbing):用于匹配的字符称为通配符(Wildcard)
    • 命令代换:``或$()中的是一条命令
    • 算数代换:$(())中的Shell变量取值将转换成整数
    • 转义字符:\用于去除紧跟其后的单个字符的特殊意义
    • 单引号、双引号:保持引号内所有字符的字面值
  • bash启动脚本
    • 可以把环境变量和alias、umask设置放在启动脚本中,每次启动Shell时都生效
    • bash的启动方式
      • 作为交互登录Shell启动,或使用--login参数启动
      • 交互非登录Shel启动
      • 非交互启动
      • 以sh命令启动
    • Shell脚本语法
      • 条件测试:test 或 [
      • if/then/elif/else/fi
      • case/esac
      • for/do/done
      • while/do/done
      • 位置参数和特殊变量
      • 函数
    • Shell脚本的调试方式
      • -n
      • -v
      • -x

正则表达式

  • 引言

    • 正则表达式:规定一些特殊语法表示字符类、数量限定符和位置关系,然后用这些特殊语法和普通字符串一起表示一个模式(Pattern)
    • 模式包含的信息:字符类(Character Class)、数量限定符(Quantifier),字符间位置关系
    • 应用:验证用户输入(ip、email)格式是否合法
  • 基本语法
  • 常用命令
    • grep
    • sed:流编辑器(Stream Editor),在Shell脚本中作为过滤器使用,把前一个程序的输出引入sed的输入,经过编辑后转换为另一种格式输出  
    • awk:以行或列为处理单位

信号

  • 基本概念

    • 按下Ctrl-C产生的信号发给前台进程(硬件中断),CPU从用户态切换到内核态处理中断
    • 信号相对于进程的控制流程来说是异步的
    • kill -l 查看系统定义的信号列表,每个信号有一个标号和一个宏名称,宏定义可在signal.h中找到
    • 每个信号都有产生条件和默认的处理动作
  • 产生信号
  • 阻塞信号
    • 执行信号的处理动作称为信号递达(Delivery)
    • 信号从产生到递达之间的状态称为信号未决(Pending)
    • 进程可选择阻塞(Block)某个信号,被阻塞的信号产生时保持在未决状态,直到进程解除阻塞,才执行递达动作
  • 捕捉信号
    • 信号处理动作是用户自定义函数(signal handler),信号递达时调用这个函数,返回后自动执行系统调用sigreturn再次进入内核态,没有新的信号递达,返回main的上下文继续执行

终端、作业控制与守护进程

  • 终端

    • 串口终端:嵌入式开发中,目标板的每个串口对应一个终端设备
    • 虚拟终端(Virtual Terminal):/dev/tty1~/dev/tty6
    • 终端缓冲:终端设备的输入/输出缓冲队列
    • 终端登录:内核中处理终端设备的模块包括硬件驱动程序和线路规程(Line Discipline)
    • 网络终端/图形终端(窗口):数目不限,通过伪终端(Pseudo TTY)实现,一套伪终端由一个主设备(PTY Master,相当于键盘和显示器)和一个从设备(PTY Slave)组成

  • 作业控制(Job Control):

    • 作业(Job)指进程组(Process Group),Shell可以同时运行一个前台作业和多个后台作业
    • Session:拥有相同控制终端的一组进程

  • 守护进程(Daemon)

    • Linux中的系统服务进程,没有控制终端,不能和用户交互,不受用户登录和注销的影响一直运行

线程

  • 线程的概念

    • 在一个进程中同时执行多个控制流程,如一个图形界面的下载软件,要一边和用户交互,等待和处理用户的鼠标键盘事件,一边同时下载多个文件,等待和处理从多个网络主机发来的数据
    • 多任务的“等待-处理”循环可以用多线程实现
    • 同一进程的多个线程共享同一地址空间
  • 线程控制
    • 创建线程
    • 终止线程
  • 线程间同步
    • 互斥锁(Mutex, Mutual Exclusive Lock):代表资源的可用数量,非0即1,获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其他线程,没有锁的线程只能等待而不能访问共享数据,保证了“读-修改-写”是原子操作(要么都执行,要么都不执行),不会执行到中间被打断,也不会在其他处理器上并行这个操作
    • 死锁(Deadlock)
    • 条件变量(Condition Variable)
    • 信号量(Semaphore):可用的资源数量,可大于1
    • 其他线程间同步机制

TCP/IP协议基础

  • TCP/IP协议栈与数据包封装

    • 数据包名称:传输层--段(segment),网络层--数据报(datagram),链路层--帧(frame)

  • 以太网帧格式
  • ARP数据报格式
  • IP数据报格式
  • IP地址与路由
    • 使用私有IP地址的主机可通过代理服务器或NAT(网络地址转换)链接到Internet
    • 本机回环测试(loop back)

    • 路由表
  • UDP段格式
  • TCP协议

socket编程

  • 预备知识
  • 基于TCP协议的网络程序
    • select:网络程序中的一个系统调用,可同时监听多个阻塞的文件描述符(如多个网络连接),哪个有数据就先处理哪个,从而不需fork和多进程就可实现并发服务的server
  • 基于UDP协议的网络程序
  • UNIX Domain Socket IPC
  • 简单的Web服务器

参考

Linux C编程一站式学习

http://docs.linuxtone.org/ebooks/C&CPP/c/

IBM教程

https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html

硬连接和软连接

https://blog.csdn.net/Y_Hanxiao/article/details/83986797

https://www.cnblogs.com/diantong/p/10507132.html

[Linux] Linux C编程一站式学习 Part.3的更多相关文章

  1. Linux网络编程一站式学习

    提要 学过非常多遍计算机网络,依旧不会网络编程. 看完这篇文章之后就不会是这样了. 环境:Ubuntu14.04 64bit 何为Socket 是基于TCP/IP的网络应用编程中使用的有关数据通信的概 ...

  2. 有关于《Linux C编程一站式学习》(备份)

    Linux C编程一站式学习 -- PDF版本,共37章: Linux C编程一站式学习 -- 在线版,来自灰狐: Linux C编程一站式学习 -- 在线版,来自亚嵌教育: Linux C一站式学习 ...

  3. gdb笔记 ---《Linux.C编程一站式学习》

    gdb笔记 ---<Linux.C编程一站式学习> 单步执行和跟踪函数调用 函数调试实例 #include <stdio.h> int add_range(int low, i ...

  4. Liunx+C编程一站式学习

    Liunx+C编程一站式学习这本书有什么特点?面向什么样的读者?这本书最初是为某培训班的嵌入式系统Linux工程师就业班课程量身定做的教材之一.该课程是为期四个月的全日制职业培训,要求学员毕业时具备非 ...

  5. [Linux] Linux C编程一站式学习 Part.1

    C语言入门 程序基本概念 程序和编程语言 C语言--(编译器)--汇编语言--(汇编器)--机器语言(目标代码 / 可执行代码) 可移植 / 平台无关:平台指计算机体系结构或操作系统,或二者的组合.不 ...

  6. [Linux] Linux C编程一站式学习 Part.2

    C语言本质 计算机中数的表示 浮点数:符号位+指数部分(2的多少次方)+尾数部分(小数点后的数字) 用偏移的指数(Biased Exponent)表示负指数 正规化(Normalize):尾数部分最高 ...

  7. Linux C 编程一站式学习

    个人认为这是一个挺不错的从C语言到Linux系统开发的教程,这本是两个网上的文档. 其中 一本是<How To Think Like A Computer Scientist: Learning ...

  8. Linux C编程一站式学习读书笔记——socket编程

    前言 研一的时候写过socket网络编程,研二这一年已经在用php写api都快把之前的基础知识忘干净了,这里回顾一下,主要也是项目里用到了,最近博客好杂乱啊,不过确实是到了关键时刻,各种复习加巩固准备 ...

  9. Linux C编程一站式学习

    http://docs.linuxtone.org/ebooks/C&CPP/c/ 很全面的介绍

随机推荐

  1. 第14 章 : Kubernetes Service讲解

    Kubernetes Service 本文将主要分享以下四方面的内容: 为什么需要 K8s service: K8s service 用例解读: K8s service 操作演示: K8s servi ...

  2. Chrome插件开发入门

    最近学习了Chrome插件的开发,总体来说上手还是很容易的,因为浏览器插件本质上依旧是网页,写几个demo基本就了解了他的开发过程. 完整项目:xmy6364/chrome-extension-get ...

  3. Jmeter(四十三) - 从入门到精通高级篇 - Jmeter之IP伪装和欺骗(详解教程)

    1.简介 我们从小接受的教育就是不要撒谎,要做一个诚实的孩子,但是在现实生活中有时候说一个善意的谎言也不是可以的.这里由于服务器各种安全机制的限制和校验,因此我们不得不欺骗一下服务器,今天宏哥就给大家 ...

  4. 473. Matchsticks to Square

    Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match ...

  5. 关于Spring Data JPA 多表查询 返回自定义Vo的问题记录

    这两天开了一个新项目,使用SpringBoot+SpringData,  刚做了一个小功能,都是一张表的操作没什么问题,今天设计到了两张表联查,两张表各取了几个字段,组合成了一个vo, 当我用原生sq ...

  6. 【工具类】获取请求头中User-Agent工具类

    public class AgentUserKit { private static String pattern = "^Mozilla/\\d\\.\\d\\s+\\(+.+?\\)&q ...

  7. hdu4846 最大子正方形(dp)

    题意:       给你一个图,让你找到最大的子矩形. 思路:       之前做过一个最大子矩阵,记得当时是用三种方法做的,两种都是瓶颈法,第三种是dp,结果今天的用瓶颈吧怎么都过不去,哎!不知道为 ...

  8. hdu2438 三分

    题意:       给你个90度的转弯,和一辆标准矩形的车,问你这台车能不能拐过去.. 思路:      求出靠近最里侧的那条边所在的直线(这个图形右下角为坐标原点)       y = x * ta ...

  9. hdu3415单调队列

    题意:       给你一个数字组成的环,要求在里面找到一个最大的子序列,使得和最大,要求: (1)子序列长度不能超过k (2)如果子序列和相同要起点最小的 (3)如果起点相同要长度最小的 思路:   ...

  10. JEET W1S运动蓝牙耳机简评

    对于我这种喜欢运动的人来说,很早之前就一直想买个运动蓝牙耳机了.这次正好有此机会可以评测来自JEET的W1S运动蓝牙耳机,真的是非常的幸运! 终于,在期盼中,我的来自深圳的快递隔了四天终于到了!JEE ...