linux操作系统原理
文章平均质量分 76
1314ZYX
这个作者很懒,什么都没留下…
展开
-
task_struct
task_struct是进程描述符。操作系统通过task_struct感知进程的存在。我学习内核的入口点就是该结构体。现在就分析分析该结构体吧。该结构体在内核中的位置:./include/linux/sched.h struct task_struct { volatile long state; 这个字段来描述进程的状态。这儿有个关键词vola转载 2015-01-27 16:12:50 · 1283 阅读 · 0 评论 -
Linux操作系统常见文件结构体
大家都知道进程,可是知道linux是怎么管理其进程的吗?每一个进程都有一个进程描述符,具体是task_struct结构体存储相关的信息,在linux/sched.h文件里定义,那么我们先看看linux内核3.0版本的task_struct结构体的定义吧(删除了不必要的字段,只保留了重要的字段)。同时欢迎大家转载和交流。struct task_struct { //这个是进程转载 2015-01-29 09:55:11 · 724 阅读 · 0 评论 -
二级指针和内存分配问题 形参和实参
char p是声明一个字符类型变量p,char * p1是声明一个字符类型的指针变量p1,那么char ** p2就相当与给char类型的指针变量再声明一个指针.(2级指针)举个例子,假如:char p='a';//假设声明了p后,p在内存的1000处,则&p=1000(&为取变量首地址)char * p1=&p;//则p1=1000,*p1=p='a',p1就和p关联了;假设p1被放在2转载 2015-02-06 20:08:27 · 2049 阅读 · 1 评论 -
形参和实参的区别
形参:全称为"形式参数"是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传如的参数.实参:全称为"实际参数"是在调用时传递个该函数的参数.--------------------------------------------------------------------------------void Exchg1(int x, int y) {转载 2015-02-06 20:32:19 · 508 阅读 · 0 评论 -
进程页表两级结构:页目录和页表页
进程页表的基本结构仅适合于小进程地址空间,在大地址空间下,该结构发生了变化。大虚址空间下的内存进程页表结构采用页表页和页目录。 32位意味着虚址空间可达4GB 虚址空间计算方法:32位的编址为232,232=210*210*210*22=4GB1k=1024b1m=1024K1g=1024M 若虚址空间为2GB,在页长4KB时共有2G=1024K*1024K转载 2015-02-10 18:20:36 · 11352 阅读 · 0 评论 -
二维数组
int arr[5][]; 这样的定义是无法编译通过的。因为你没有给出二维数组的第二个维度。即可以写成 int arr[][5],或者int arr[3][5]。也就是说,定义二维数组时必须写明第二个维度,而第一个维度可以给也可以不给,如果不给第一个维度,编译器会根据你的初始化语句自动决定第一维度。二维数组在内存中其实是一个平坦的一维数组,下面具体说明:int arr[3][5] 和转载 2015-02-11 09:58:46 · 573 阅读 · 0 评论 -
数组名和数组名取地址的区别
以下代码会打印出什么样的日志呢?[cpp] view plaincopy#include int a[2] = {1,2}; int main(){ printf("a = %p\n", a); // I printf("&a = %p\n", &a); // II转载 2015-02-11 09:26:51 · 459 阅读 · 0 评论 -
Linux 2.6 内核软中断(softirq)执行分析
今天无意中看了眼 Linux 2.6 内核的软中断实现,发现和以前我看到的大不相同(以前也是走马观花,不大仔细),能说改动非常大。连 softirq 的调用点都不相同了,以前是三个调用点,今天搜索了一下原始码,发目前多出了ksoftirqd 这个东西后,softirq 在系统中的调用点仅是在 ISR 返回时和使用了 local_bh_enable() 函数后被调用了。网卡部分的显示调用,我觉得应该转载 2015-01-25 12:14:30 · 411 阅读 · 0 评论 -
linux 系统调用执行过程
简单总结一下linux的系统调用过程:层次如下:用户程序------>C库(即API):INT 0x80 ----->system_call------->系统调用服务例程-------->内核程序先说明一下,我们常说的用户API其实就是系统提供的C库。系统调用是通过软中断指令 INT 0x80 实现的,而这条INT 0x80指令就被封装在C库的函数中。(软转载 2015-01-25 12:47:30 · 363 阅读 · 0 评论 -
linux2.6.29 CFS调度详细分析(一)
linux2.6.29 CFS调度详细分析(一) 众所周知,linux最新的内核采用了CFS的调度机制,网上也有不少文章对CFS调度的源码做了详细的分析,但是大部分的文章太注重细节了,所以没有把CFS的原理进行一下从整体上的概括,基于这个原因,本文要从CFS调度的基本原理以及在公平调度类的整个执行过程为主线来进行详细的说明。 CFS(comple转载 2015-01-25 10:03:42 · 316 阅读 · 0 评论 -
linux线程的退出--附:一个变量,两个精彩
linux的2.6内核更好的实现了内核级别的线程,使得线程的语义更加符合posix的约定,总的来说,线程会在两种地方退出,第一个是正常退出,第二种是异常退出,正常退出的情况下,比如在一个进程的一个线程调用exec的时候,那么所有的别的线程都会退出,另外在一个线程调用exit库函数的时候或者调用group_exit系统调用的时候,整个线程都会退出,异常的情况下,接收到内核的严重错误信号的时候也会退出转载 2015-02-02 14:16:25 · 483 阅读 · 0 评论 -
进程内核栈、用户栈
进程内核栈、用户栈1.进程的堆栈 内核在创建进程的时候,在创建task_struct的同事,会为进程创建相应的堆栈。每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。2.进程用户栈和内核栈转载 2015-02-02 08:56:28 · 322 阅读 · 0 评论 -
多线程信号总结
linux 多线程信号总结(一)1. 在多线程环境下,产生的信号是传递给整个进程的,一般而言,所有线程都有机会收到这个信号,进程在收到信号的的线程上下文执行信号处理函数,具体是哪个线程执行的难以获知。也就是说,信号会随机发个该进程的一个线程。2 signal函数BSD/Linux的实现并不在信号处理函数调用时,恢复信号的处理为默认,而是在信号处理时阻塞此信号,直到信号处理函数返回。转载 2015-01-30 15:56:01 · 1600 阅读 · 0 评论 -
waitpid函数源码
int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)//挂起当前进程,直到pid指定的子进程退出终止或者收到要求终止该进程 的信号 ,或者需要调用 一个信号处理函数{ int flag, code; struct task_struct ** p; verify_area(s转载 2015-01-29 09:06:21 · 1107 阅读 · 0 评论 -
Linux的进程调度时机(Schedule函数何时调用)
Linux在众多进程中是怎么进行调度的,这个牵涉到Linux进程调度时机的概念,由Linux内核中Schedule()的函数来决定是否要进行进程的切换,如果要切换的话,切换到哪个进程等等。Linux进程调度时机主要有:1、进程状态转换的时刻:进程终止、进程睡眠;2、当前进程的时间片用完时(current->counter=0);3、设备驱动程序4、进程从中断转载 2015-01-30 08:48:47 · 641 阅读 · 0 评论 -
信号 中断系统调用 递送
1 前言 写作本文的目的和其它文章略有不同,不是为了系统和全面的介绍”信号”这个子系统,--虽然它不复杂,其内容也不是一篇短短的文章所能够覆盖的,而是要回答自己的疑惑,解决工作中遇到的一些问题,理解那些不能够马上了解的部分。说到底,可以将这篇文章看作问题的答案。 曾经遇到的问题放在最后一节”问题与答案”中,在阅读正文之前先扫描一下问题可能更加有助于理解文章中的内容。 欢迎大家对转载 2015-01-30 09:58:33 · 478 阅读 · 0 评论 -
阻塞访问原理——等待队列
有些时候,一个系统调用可能无法马上取到或者送出数据:一个温度采集器如果没有采用中断或者轮询的策略,而是在用户发出请求时才进行采集,并在一定的时间后返回结果。如果用户程序希望调用read或write并且在调用返回时能确保得到想要的结果,那么用户程序应该阻塞,直到有结果或者错误后返回,用户程序的阻塞体现为进程的睡眠,也即系统调用中将进程状态切换为睡眠态。 睡眠和等待队列一个进程转载 2015-01-30 09:34:39 · 549 阅读 · 0 评论 -
打开文件的内核源码分析
一、概要 用户进程在能够读/写一个文件之前必须要先打开这个文件,从概念上说是一个进程与文件系统之间的一种有链接的通信,对于打开文件实质就是在进程和文件之间建立起连接,而“打开文件号”就是唯一的标识这个连接。在文件系统的处理当中,每当一个进程重复打开同一个文件时就建立起一个由file数据结构代表的独立的上下文。通常,一个file数据结构,即一个读/写文件的上下文,都是由一个“打开文件号”加以转载 2015-01-29 14:51:03 · 516 阅读 · 0 评论 -
list_for_each_entry
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \转载 2015-01-30 15:02:49 · 368 阅读 · 0 评论 -
list_for_each
Linux系统中的每个进程都有一个父进程(init进程除外);每个进程还有0个或多个子进程。在进程描述符中parent指针指向其父进程,还有一个名为children的子进程链表(父进程task_struct中的children相当于链表的表头)。而我们可以使用list_for_each(/include/linux/list.h)来依次遍历访问子进程:struct task_str转载 2015-01-30 14:32:48 · 800 阅读 · 0 评论 -
select函数的实现源码
代码摘自:linux-2.6.29sys_select -> core_sys_select -> do_selectint do_select(int n, fd_set_bits *fds, struct timespec *end_time){ ktime_t expire, *to = NULL; struct p转载 2015-01-30 11:12:52 · 819 阅读 · 0 评论 -
list_entry()详解
Linux内核中,获取节点地址的函数list_entry()非常常用,由于其定义有点晦涩,先解析如下:list_entry的宏定义:#define list_entry(ptr, type, member) / ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 这个倒是不难理解:从一个转载 2015-01-30 14:22:12 · 378 阅读 · 0 评论 -
mount实现的过程
本质上,Ext3 mount的过程实际上是inode被替代的过程。例如,/dev/sdb块设备被mount到/mnt/alan目录。那么mount这个过程所需要解决的问题就是将/mnt/alan的dentry目录项所指向的inode屏蔽掉,然后重新定位到/dev/sdb所表示的inode索引节点。在没有分析阅读linux vfs mount代码的时候,我的想法是修改dentry所指向的inod转载 2015-02-14 11:00:35 · 1046 阅读 · 0 评论