linux环境系统编程
文章平均质量分 89
主要分为基础知识,文件与I/O,进程,信号和管道五部分来讲解。
代码已经分类上传至 https://github.com/JnuSimba/APUE
s1mba
这个作者很懒,什么都没留下…
展开
-
从汇编角度来理解linux下多层函数调用堆栈运行状态
我们用下面的代码来研究函数调用的过程。 C++ Code 12345678910111213141516int bar(int c, int d){ int e = c + d; return e;}int foo(int a, int b原创 2014-05-06 21:05:03 · 4513 阅读 · 0 评论 -
套接字socket 的地址族和类型、工作原理、创建过程
注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早,分析的版本为2.4.16,故出现的一些概念可能跟最新版本内核不同。此书已经开源,阅读地址原创 2013-09-17 10:21:45 · 8166 阅读 · 0 评论 -
Ext2文件系统布局,文件数据块寻址,VFS虚拟文件系统
注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早,分析的版本为2.4.16,故出现的一些概念可能跟最新版本内核不同。此书已经开源,阅读地址原创 2013-09-17 09:40:11 · 5119 阅读 · 0 评论 -
内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
一、内存管理概述(一)、虚拟内存实现结构(1)内存映射模块(mmap):负责把磁盘文件的逻辑地址映射到虚拟地址,以及把虚拟地址映射到物理地址。(2)交换模块(swap):负责控制内存内容的换入和换出,它通过交换机制,使得在物理内存的页面(RAM 页)中保留有效的页 ,即从主存中淘汰最近没被访问的页,保存近来访问过的页。(3)核心内存管理模块(原创 2013-09-17 08:47:11 · 7643 阅读 · 0 评论 -
X86 寻址方式、AT&T 汇编语言相关知识、AT&T 与 Intel 汇编语言的比较、gcc 嵌入式汇编
一、X86 寻址方式x86的通用寄存器有8个。这些寄存器在大多数指令中是可以任意选用的,比如movl 指令可以把一个立即数传送到eax 中,也可传送到ebx 中。但也有一些指令规定只能用其中某个寄存器做某种用途,例如除法指令idivl 要求被除数在eax 寄存器中,edx 寄存器必须是0,而除数可以在任意寄存器中,计算结果的商数保存在eax 寄存器中(覆盖原来的被除数),余数保存在ed原创 2013-09-16 21:29:55 · 12033 阅读 · 0 评论 -
进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
一、管道在Linux 中,管道是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现如下所述。• 限制管道的大小。实际上,管道是一个固定大小的缓冲区。在Linux 中,该缓冲区的大小为1 页,即4KB,使得它的大小不像文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变原创 2013-09-16 19:43:24 · 9365 阅读 · 0 评论 -
时间系统、进程的调度与切换
一、时间系统大部分PC 机中有两个时钟源,他们分别叫做RTC 和OS(操作系统)时钟。RTC(Real Time Clock,实时时钟)也叫做CMOS 时钟,它是PC 主机板上的一块芯片(或者叫做时钟电路),它靠电池供电,即使系统断电,也可以维持日期和时间。由于它独立于操作系统,所以也被称为硬件时钟,它为整个计算机提供一个计时标准,是最原始最底层的时钟数据。OS 时钟产原创 2013-09-16 19:13:24 · 4918 阅读 · 1 评论 -
进程控制块PCB结构 task_struct 描述
一、task_struct 结构描述1.进程状态(State)进程执行时,它会根据具体情况改变状态。进程状态是调度和对换的依据。Linux 中的进程主要有如下状态,如表4.1 所示。(1)可运行状态处于这种状态的进程,要么正在运行、要么正准备运行。正在运行的进程就是当前进程(由current 宏 所指向的进程),而准备运行的进程只要得到CPU原创 2013-09-16 10:46:21 · 10195 阅读 · 5 评论 -
中断机制和中断描述符表、中断和异常的处理
1、中断向量Intel x86 系列微机共支持256 种向量中断,为使处理器较容易地识别每种中断源,将它们从0~256 编号,即赋予一个中断类型码 n,Intel 把这个8 位的无符号整数叫做一个向量,因此,也叫中断向量。所有256 种中断可分为两大类:异常和中断。异常又分为故障(Fault)和陷阱(Trap),它们的共同特点是既不使用中断控制器,又不能被屏蔽。中断又分为外部可屏蔽原创 2013-09-16 10:09:26 · 8918 阅读 · 1 评论 -
80386的分段机制、分页机制和物理地址的形成
MOVE REG,ADDR ; 它把地址为ADDR(假设为10000)的内存单元的内容复制到REG 中在8086 的实模式下,把某一段寄存器(段基址)左移4 位,然后与地址ADDR 相加后被直接送到内存总线上,这个相加后的地址(20位)就是内存单元的物理地址,而程序中的这个地址ADDR就叫逻辑地址(或叫虚地址)。在80386 的段机制中,逻辑地址由两部分组成,即原创 2013-09-15 19:50:35 · 5689 阅读 · 0 评论 -
80386的各种寄存器一览
注:本分类下文章大多整理自《深入分析linux内核源代码》一书,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早,分析的版本为2.4.16,故出现的一些概念可能跟最新版本内核不同。此书已经开源,阅读地址 http://www.kerneltravel.net1、通用寄原创 2013-09-15 19:06:50 · 3322 阅读 · 0 评论 -
linux系统编程之基础必备(七):read/write函数与(非)阻塞I/O的概念
一、read/write 函数read函数从打开的设备或文件中读取数据。#include ssize_t read(int fd, void *buf, size_t count);返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中原创 2013-05-20 16:40:34 · 16119 阅读 · 4 评论 -
linux系统编程之基础必备(六):可重入函数、线程安全、volatile
一、 POSIX 中对可重入和线程安全这两个概念的定义: Reentrant Function:A function whose effect, when called by two or more threads,is guaranteed to be as if the threads each executed the function one after anothe原创 2013-05-20 09:40:06 · 5180 阅读 · 2 评论 -
linux系统编程之基础必备(五):Linux进程地址空间和虚拟内存
一、虚拟内存先来看一张图(来自《Linux内核完全剖析》),如下:分段机制:即分成代码段,数据段,堆栈段。每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低特权级(用户),每当程序试图访问(权限又分为可读、可写和可执行)一个段时,当前特权级CPL就会与段的特权级进行比较,以确定是否有权限访问。每个特权级都有自己的程序栈,当程序从一个特权级切换到另原创 2013-05-12 16:46:20 · 7495 阅读 · 0 评论 -
linux系统编程之基础必备(四):C 标准库IO缓冲区和内核缓冲区的区别
1.C标准库的I/O缓冲区 UNIX的传统 是Everything is a file,键盘、显示器、串口、磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也可以像普通文件(保存在磁盘上的文件)一样打开、读、写和关闭,使用的函数接口是相同的。用户程序调用C标准I/O库函数读写普通文件或设备,而这些库函数要通过系统调用把读写请求传给内核 ,最终由内核驱动磁原创 2013-04-16 12:19:09 · 8078 阅读 · 2 评论 -
linux系统编程之基础必备(三):文件描述符file descriptor与inode的相关知识
每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的 信息,称为进程描述符(Process Descriptor),而在操作系统理论中称为进程控制块 (PCB,Process Control Block)。task_struct中有一个指针(struct files_struct *files; )指向files_struct结构体,称为文件 描述符表,其中每个表项包原创 2013-04-16 12:16:02 · 22781 阅读 · 13 评论 -
linux系统编程之基础必备(二):C 标准IO 库函数与Unbuffered IO函数
先来看看C标准I/O库函数是如何用系统调用实现的。 fopen(3) 调用open(2)打开指定的文件,返回一个文件描述符(就是一个int 类型的编号),分配一 个FILE 结构体,其中包含该文件的描述符、I/O缓冲区和当前读写位置等信息,返回这 个FILE 结构体的地址。 fgetc(3) 通过传入的FILE *参数找到该文件的描述符、I/O缓冲区和当前读原创 2013-04-16 12:05:14 · 5445 阅读 · 4 评论 -
linux系统编程之基础必备(一):计算机体系结构一点基础知识
无论是在CPU外部接总线的设备还是在CPU内部接总线的设备都有各自的地址范围,都可以像访问内存一样访问,很多体系结构(比如ARM)采用这种方式操作设备,称为内存映射I/O(Memory-mappedI/O)。但是x86比较特殊,x86对于设备有独立的端口地址空间,CPU核需要引出额外的地址线来连接片内设备(和访问内存所用的地址线不同),访问设备寄存器时用特殊的in/out指令(汇编),而不是和访问原创 2013-04-16 11:57:31 · 6217 阅读 · 9 评论 -
linux系统编程之管道(三):命名管道FIFO和mkfifo函数
进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,前面讲过的匿名管道是用打开的文件描述符来标识的。如果要互相通信的几个进程没有从公共祖先那里继承文件描述符,它们怎么通信呢?内核提供一条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。FIFO原创 2013-05-21 11:03:53 · 38315 阅读 · 4 评论 -
linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF
一、当没有数据可读时O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。示例程序如下: C++ Code 123456789101112131415161原创 2013-05-21 09:39:15 · 9355 阅读 · 1 评论 -
linux系统编程之管道(一):匿名管道和pipe函数
一、进程间通信每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。如下图所示。二、管道是一种最基本的IPC机制,由pipe函原创 2013-05-20 15:53:51 · 11560 阅读 · 5 评论 -
linux系统编程之信号(六):竞态条件与sigsuspend函数
一、利用pause和alarm函数实现sleep函数#include int pause(void);pause函数使调用进程挂起直到有信号递达。如果信号的处理动作是终止进程,则进程终止,pause函数没有机会返回;如果信号的处理动作是忽略,则进程继续处于挂起状态,pause不返回;如果信号的处理动作是捕捉,则调用了信号处理函数之后pause返回-1,errno设置为EINTR,所以p原创 2013-05-20 12:43:20 · 4341 阅读 · 1 评论 -
linux系统编程之信号(五):实时信号与sigqueue函数
一、sigqueue函数功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。原型:int sigqueue(pid_t pid, int sig, const union sigval value);参数: sigqueue的第一个参数是指定接收信号的进程id,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构unio原创 2013-05-19 13:04:02 · 9492 阅读 · 1 评论 -
linux系统编程之信号(四):信号的捕捉与sigaction函数
一、内核如何实现信号的捕捉如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下:1. 用户程序注册了SIGQUIT信号的处理函数sighandler。2. 当前正在执行main函数,这时发生中断或异常切换到内核态。3. 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT原创 2013-05-19 11:30:36 · 21090 阅读 · 5 评论 -
linux系统编程之信号(三):信号的阻塞与未决
一、信号在内核中的表示实际执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示可以看作是这样的:原创 2013-05-18 21:52:58 · 8552 阅读 · 9 评论 -
linux系统编程之信号(二):一些信号发送函数和不同精度的睡眠
一、kill, raise, killpg 函数int kill(pid_t pid, int sig);int raise(int sig);int killpg(int pgrp, int sig);kill命令是调用kill函数实现的,kill函数可以给一个指定的进程或进程组发送指定的信号,其中kill 函数的pid 参数取值不同表示不原创 2013-05-18 19:46:09 · 4053 阅读 · 0 评论 -
linux系统编程之信号(一):信号基本概述
一、为了理解信号,先从我们最熟悉的场景说起:1. 用户输入命令,在Shell下启动一个前台进程。2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断。3. 如果CPU当前正在执行这个进程的代码,则该进程的用户空间代码暂停执行,CPU从用户态切换到内核态处理硬件中断。4. 终端驱动程序将Ctrl-C解释成一个SIGINT信号,记在该进程的PCB中(也可以说发送了一个SIGINT信原创 2013-05-17 18:38:32 · 5697 阅读 · 1 评论 -
linux系统编程之进程(五):终端、作业控制与守护进程
一、终端的概念在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),控制终端是保存在PCB中的信息,而我们知道fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端。默认情况下(没有重定向),每个进程的标准输入、标准输出和标准错误输出都指向控制终端,进程从标准输入读也就是原创 2013-05-15 20:54:31 · 6335 阅读 · 4 评论 -
linux系统编程之进程(四):wait/waitpid函数与僵尸进程、fork 2 times
一、僵尸进程当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。父进程查询子进程的退出状态可以用wait/waitpid函数。二、如何避免僵尸进程当一个子进程结束运行时,它原创 2013-05-15 19:41:47 · 6198 阅读 · 1 评论 -
linux系统编程之进程(三):exec系列函数和system函数
一、exec替换进程映象在进程的创建上Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行。当然,exec系列的函数也可以将当前进程替换掉。二、exec关联函数组包含头文件功能用exec函数可以把当前进程替换为一个新进程。exec原创 2013-05-15 16:26:59 · 5448 阅读 · 6 评论 -
linux系统编程之进程(二):fork函数相关总结
一、fork系统调用包含头文件 和 函数功能:创建一个子进程函数原型 pid_t fork(void);参数:无参数。返回值:如果成功创建一个子进程,对于父进程来说返回子进程ID如果成功创建一个子进程,对于子进程来说返回值为0如果为-1表示创建失败(1)、使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进原创 2013-05-15 09:15:53 · 6849 阅读 · 1 评论 -
linux系统编程之进程(一):进程基本概述
一、什么是进程从用户的角度来看进程是程序的一次执行过程。从操作系统的核心来看,进程是操作系统分配的内存、CPU时间片等资源的基本单位。进程是资源分配的最小单位。每一个进程都有自己独立的地址空间与执行状态。像UNIX这样的多任务操作系统能够让许多程序同时运行,每一个运行着的程序就构成了一个进程。二、进程数据结构进程的静态描述:由三部分组成:PCB、有关程序段和原创 2013-05-14 13:07:00 · 3405 阅读 · 0 评论 -
linux系统编程之文件与I/O(六):fcntl 函数与文件锁
一、fcntl函数功能:操纵文件描述符,改变已打开的文件的属性int fcntl(int fd, int cmd, ... /* arg */ );cmd的取值可以如下:复制文件描述符F_DUPFD (long)设置/获取文件描述符标志F_GETFD (void)F_SETFD (long)设置/获取文件状态标志F_GETFL (vo原创 2013-05-14 11:26:59 · 14541 阅读 · 3 评论 -
linux系统编程之文件与I/O(五):文件的内核结构file和dup实现重定向
一、打开文件内核数据结构1、一个进程打开两个文件文件状态标志:读、写、追加、同步、非阻塞等2、一个进程两次打开同一文件3、两个进程打开同一文件示例程序: C++ Code 1234567891011121314151617181原创 2013-05-14 16:51:48 · 11407 阅读 · 1 评论 -
linux系统编程之文件与I/O(四):文件的属性
一、读取文件元数据int stat(const char *path, struct stat *buf);int fstat(int fd, struct stat *buf);int lstat(const char *path, struct stat *buf); stat() stats the file pointed to by path and fill原创 2013-05-13 16:10:27 · 3199 阅读 · 0 评论 -
linux系统编程之文件与I/O(三):目录的操作
一、目录的访问功能说明:打开一个目录原型:DIR* opendir(char *pathname);返回值:打开成功,返回一个目录指针打开失败,则返回NULL功能说明:访问指定目录中下一个连接的细节原型:struct dirent* readdir(DIR *dirptr);返回值:返回一个指向dirent结构的指针,它包含指定目录中原创 2013-05-12 22:41:20 · 2909 阅读 · 2 评论 -
linux系统编程之文件与I/O(二):文件的读取写入
一、read系统调用一旦有了与一个打开文件描述相关连的文件描述符,只要该文件是用O_RDONLY或O_RDWR标志打开的,就可以用read()系统调用从该文件中读取字节 函数原型:ssize_t read(int fd, void *buf, size_t count);参数:fd :想要读的文件的文件描述符buf : 指向内存块的指针,从文件中读取来的字节放到这个内存原创 2013-05-12 21:45:07 · 3825 阅读 · 0 评论 -
linux系统编程之文件与I/O(一):文件的打开关闭
一、文件描述符对于Linux而言,所有对设备或文件的操作都是通过文件描述符进行的。当打开或者创建一个文件的时候,内核向进程返回一个文件描述符(非负整数)。后续对文件的操作只需通过该文件描述符,内核记录有关这个打开文件的信息(file结构体)。一个进程启动时,默认打开了3个文件,标准输入、标准输出、标准错误,对应文件描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2原创 2013-05-12 20:12:08 · 4351 阅读 · 3 评论