文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Linux FAQ(很杂)

Linux FAQ(很杂)

时间:2007-04-17  来源:Echo CHEN

内核介绍和基本配置
(lkml指Linux kernel Mailing List)
1. Q: 什么是试验版内核?
```A: (lkml)Linux内核版本分为两个开发树:试验树(版本号为奇数,如:1.3.xx 或 2.1.x )和稳定树(版本号为偶数,如1.2.xx,2.0.xx)。试验树更新得很快,通常用于测试新的特性,算法,设备驱动程序,等等。试验树的内核也许会产生奇怪的操作,这样就有可能导致数据丢失,或者机器死锁等等。
2. Q: 什么是稳定版内核?
```A: (lkml)稳定树具有定义良好的特性,更少的bug,可靠的驱动程序。虽然稳定树的更新比实验树慢很多,通常有一些比别的版本好的"最佳版本"。Linux的发行版通常是基于这些"最佳版本",而不一定是最新的版本。
3. Q: 内核版本号为f.g.hhprei表示什么?
```A: (lkml)这是Linux版本f.g.hh的中间版。通常i < 5,但是也有例外,如2.0.34prei就具有i = 1 to 16个版本。有时候"pre"会被的Linux版本维护者的名字的简写所取代。如2.1.105ac4表示Alan Cox发布的内核版本2.1.105的第四个中间版。
4. Q: 我在哪里能下载Linux的最新内核源码?
```A: (lkml)Linux内核源码(试验树和稳定树)的主要站点是由Transmeta公司(Linus Torvalds工作的公司)维护的http://www.kernel.org/。这个站点在全球很多国家都有镜像站点。你可以通过链接http://www.CODE.kernel.org/来访问本国的镜像站点。这里,"CODE"是指国家代码。如"cn"是中国的国家代码,这样,中国的Linux内核主要镜像站点就是http://www.cn.kernel.org/。
```你也可以通过ftp访问ftp://ftp.CODE.kernel.org/pub/linux/kernel/来得到Linux内核的patch,这是Linus发布他的Linux内核的地方。其他的著名的Linux内核hacker在"people"目录下有自己的目录,他们可以在那里存放自己的内核patch。"testing"是linus存放自己的pre-release patches的地方。pre-release patches主要是其他的开发者使用的,以便他们可以与Linus的源码树保持同步。加上这些patch的内核可能比试验树的内核更加危险,它可能会 crash,甚至破坏你的文件系统。使用这些patch时,你需要特别地注意到这种风险性。
5. Q: 我在哪里能下载额外的Linux的内核的patch?
```A: (lkml)有很多地方提供不同的额外的patch,这些patch可以为Linux内核增加新的功能。这里是一个不错的站点。
6. Q: 什么是patch?
```A: patch文件(这里指Linux内核patch)是ASCII文本文件,它包含在原始代码和新代码之间的不同部分,以及一些附加的信息,如文件名,行号。通过patch程序(man patch)可以把这个patch加到一个现有的内核源码树上。
7. Q: 怎样制作Linux内核的patch?
```A: (lkml)你可以用diff程序(info diff)来制作patch。最简单的方式是在/usr/src目录下建立两个源码树,建立一个链接"/usr/src/linux",链接到修改后的源码树。然后再运行diff程序比较这两个源码树。文件/usr/src/Documentation/CodingStyle包含了更多的详细的信息,读一读这个文件。要记住:

  • 总是使用unified (-u) diff格式。
  • 不要改变源码的格式,以免使diff文件不必要的变大。察看你的编辑器设置,不要把tabs转换为空格或者相反。如果你没有特殊的原因,尽量针对最新的官方源码树做你的patch。否则,你的patch很有可能被忽略。或者,你在你的帖子中注明你的patch所针对的Linux版本号。
  • 确认你的patch只包括你这个patch所需要做的改动,而不是你对源码树的所有的改动。通常,patch限制在几个文件或目录里。最好只diff相关的文件。例如,如果我只修改了drivers/net目录下的文件driver_xyz.c,我会用以下的指令(假定你的原始源码树目录名字为 "linux-2.4.18","linux"链接指向修改后的源码树):
    cd /usr/src
    diff -u linux-2.4.18/drivers/net/driver_xyz.c \
    linux/drivers/net/driver_xyz.c > my_patch

    8. Q: 怎样安装一个patch?
    ```A: (lkml)(From /usr/src/linux/README)你可以通过安装patch来升级你的Linux源码版本。patch一般都是使用传统的gzip或比较新的 bzip2压缩后的压缩文件。如果你想要通过安装patch升级你的Linux源码版本,你需要得到所有的新的patch文件,进入到你想要升级的内核源码目录,执行:
    gzip -cd patchXX.gz | patch -p0 或:
    bzip2 -dc patchXX.bz2 | patch -p0
    (按顺序,为所有的版本号大于你当前的源码树的版本号的patch,重复xx),就完成了你的升级。你也许需要移走backup文件(xxx~或 xxx.orig),确认没有安装失败的patch(xxx# 或 xxx.rej)。如果这些文件存在,要么你,要么我犯了一个错误。
    你也可以使用patch-kernel来自动完成这些步骤。它会根据当前的内核版本来自动安装所有找到的patch。这样,运行命令:
    linux/scripts/patch-kernel linux
    指令的第一个参数是内核源码的目录。patch需要存放在当前目录,或者存放在第二个参数所指定的目录。
    ```你可以察看内核的README文件(/usr/src/linux/README)的"Installing the kernel"了解更多信息。这里是一个Linux HQ Project网站关于patch的比较好的说明。
    9. Q: 每个人都在谈论"CVS tree at vger",vger是什么?这个CVS树做什么?
    ```A: (lkml)vger.kernel.org是一个服务于Linux社团的邮件列表和网站。一个Linux内核开发树的CVS服务器是http://vger.samba.org/(译注:现在好像不能访问?),它是最新的vger.kernel.org的主源码树的镜像。需要注意CVS源码树不是官方的源码树,它主要是为了方便一些资深的Linux内核hacker的使用而建立的。由Linus Torvalds所维护的网站http://www.kernel.org/才是官方Linux源码树存放的地方,它在全球都有镜像站点。David Miller (vger CVS tree 维护者)定期地把CVS树生成的patch提交给Linus。另外,vger CVS源码树还存放Sparc, Sparc64 和一些网络方面的试验和测试的patch。
    10. Q: 我在哪里能找到更多的CVS相关的信息?
    ````A: (lkml)很多GNU/Linux的发行版都包括了CVS,你也可以访问CVS Bubbles page
    11. Q: 哪里有CVS指南?
    ````A: (lkml)这是一个你可以访问的CVS指南:
    An interactive CVS tutorial
    ````访问这个站点,你花15分钟就可以得到一个关于CVS工作流程的大概的概念(推荐)。由于目前已经开发了很多的CVS图形前端工具,你可以不用学习一般的神秘的CVS指令。
    12. Q: 怎样才能把我的patch加到官方Linux内核呢?
    ````A: (lkml)根据你的patch的内容的不同,有几种不同的方式把它加入官方Linux内核。首先,确定你所修改的代码是由谁来维护(察看 MAINTANERS文件)。如果你的patch只是一个很小的bug修复,而且你确信它"显然正确",那么,你可以把它发给适当的维护者,以及张贴到 lkml中。如果这是一个紧急的buf修复(如:一个大的安全漏洞),你也可以把它直接发给Linus,但是要记住他有可能会不理睬随意的patch,除非他认为它们"显然正确"。如果你的patch很大,例如,大片重写的代码或一个新的设备驱动程序,为了节省网络带宽和磁盘空间,你可以给lkml发送一个帖子来说明你的patch,并在你的帖子中加上你的patch的链接。最后,如果你不大确信你的patch是否正确,需要一些维护者的反馈,你可以使用私信。
    ````如果你的patch所涉及的内核部分,没有明确的维护者,那么你有三个选择:
  • 把它发送给[email protected],希望有人能看到它来提交给Linus,或者Linus本人会看到它(基本不要指望)
  • 把它发给linux-kernel,并Cc:Linus Torvalds <[email protected]>。希望Linus能够采用它。要注意没人知道Linus怎么工作,他不一定给你直接的回复。你需要检查Linus发布的patch来看他有没有采用你的patch。如果他没有采用,你也许需要重新发送一次你的patch(通常很多次)。如果等了几个礼拜或者几个月以后,经过了很多的patch的发布后,他仍然没有采用你的patch,也许你应该放弃。他也许不喜欢它。
  • 把它发给linux-kernel,并Cc:Alan Cox <[email protected]>。Alan在回复邮件方面做的好一些,他会把你的patch排队,定期的把它转发给Linux,这样,你就可以不用再担心没有人理睬它了。他总是显得品位很好,如果Alan接受了你的patch,很可能Linus也会接受。如果他不喜欢你的patch,你也许会收到一封emain给你解释。
    13. Q: 为什么Linux内核tarball包含的目录是linux而不是linux-x.y.z?
    ````A: (lkml)这是因为Linus想要这样做。这样可以使安装连续的patch更容易一些,因为不用每次都改变目录名称,这样也让Linus的生活更加轻松一些。
    14. Q: 官方Linux内核和Alan Cox的内核(ac系列的patch)有什么区别?
    ````A: (lkml)Alan的内核可以被看作Linus的内核的测试版。虽然Linus很保守,只接受明显的和经过很好测试的2.4的内核patch,Alan 维护着一系列内核patch,它们包含着新的概念,更多(与/或)更新的驱动程序,更多的插入的patch。如果这些patch能够证明自己是稳定的, Alan就会把它们提交给Linus,一般把它们加入到官方Linux内核中去。
    15. Q: Linux内核是由谁维护的?
    ````A: (lkml)最初,由Linus Torvalds来维护所有内核。当Linux内核成熟后,他把一些老的稳定的版本的维护工作委派给了其他人,而他继续维护最新的开发版。在2002年5月27号,以下的内核版本是由以下人员来维护的。
  • 2.0 David Weinehall <[email protected]>
  • 2.2 Alan Cox <[email protected]>
  • 2.4 Marcelo Tosatti <[email protected]>
  • 2.5 Linus Torvalds <[email protected]>
    16. Q: 我怎么建立我自己的内核?
    ````A: (linux天字一号)
    Let's step by step:
    **********step 1做一个新kernel出来********************
    1.从http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.12.tar.gz将最新的稳定版kernel down下来。
    2.用mv /usr/src/linux /usr/src/linux.old将原来的目录移走,用tar xfzv linux-2.4.12.tar.gz -C /usr/src/linux将代码解开.
    3.切换到/usr/src/linux目录,执行make menuconfig
    4. 可以什么都不用改,直接保存。当然也可以试着去配置内核的选项,大部分都可以直接看出是干什么的,看不出的可以查其帮助信息。
    5. 执行make dep
    6. 执行make bzImage做一个压缩的内核。
    7. 编译完成后,可以从/usr/src/linux/arch/i386/中找到新内核bzImage.
    8. 执行make modules,编译完成后将/usr/src/linux/modules拷到/lib/modules/2.4.12目录让系统自动加载这些驱动及模块,如果无法实现自动化,以后需要你用insmod去加载这些东西。

    ************step 2 使用这个新内核*********************
    1. 用cp /usr/src/linux/arch/i386/bzImage /boot将内核复制到/boot目录。
    2. 用vi /etc/lilo.conf命令来修改lilo配置文件大概如下:
    boot=/dev/hda
    map=/boot/map
    install=/boot/boot.b
    lba32 (支持大硬盘)
    timeout=50 (启动等待时间)
    default=linux (默认的启动项)
    other=/dev/hda1 (DOS操作系统)
    label=win (label)
    table=/dev/hda

    image=/boot/vmlinuz
    label=linux
    root=/dev/hda2 (hda2为旧系统的根文件系统)
    read-only
    ---------上面原系统本身会有,你需要加入下面的代码-----------------
    image=/boot/bzImage label=new (新系统的名字)
    root=/dev/hda2 (根文件系统,不一定是hda2,可根据与旧系统的根文件系统来决定)
    read-only
    3. 执行lilo



Q:什么是mm?
A:这可不是meimei哦!指的是内存管理(memory management)。是内核中的一套软件机制,用于有效管理内存的使用。

Q:内存管理的软件实现了什么功能?
A:1) 进程的保护,即进程向内存管理请求的物理页,由内存管理系统负责,不会将同一物理页(共享页面除外)映射到不同进程的虚地址空间。
2) 虚存的实现,允许所有进程使用的内存总量大于实际物理内存总量。

Q:MMU与TLB的功能?
A:TLB是MMU的核心部件,用于实现页表转换,将虚拟地址转换成实地址。
对i386而言,MMU会根据CR3中的地址(注意,这个地址是物理地址)指定的页表目录一级一级去查询,在下面情况会抛出缺页中断:
* 页目录为空(NULL)
* 页表项为空,或者对应物理页不再内存中。
* 权限不满足,比如写带只读属性的页;用户态的代码访问特权属性的页。

Q:什么是cache?
A:对于硬件,指的是一块SRAM,由于它的访问速度比较快,所以将经常访问的数据放在这块SRAM中,必要时才写回到主存储器中,这样可以提高
CPU的使用效率;对于软件,指的是主存储器中的一块空间(即缓冲区),当CPU与慢速IO进行交换数据时,先将数据放在这块内存空间中,等系统
空闲时,才真正与IO进行数据交换。比如说,当用户请求将一块数据写入磁盘时,内核会先将数据放在缓冲区中,等到系统空闲或真正有必要马上
就写数据时,内核才会执行磁盘操作,将数据写到磁盘上。在读内核源代码时,经常会看到"xx_cache_xx"之类的字眼,其实基本上都是内存缓冲区。

Q:什么是COW?
A:我第一次看它,还以为是“母牛”呢!它实际上指的是“写时拷贝(Copy On Write)”,其主要目的是提高内存管理的效率。当内核创建进程时,
为其分配的虚拟页面并没有被真正映射到物理内存上,而是被映射到一块不可写(页表项上的标志为“只读”)的内存上(对于子进程,映射的是其父
进程的物理空间),当该进程要往里面写东东时,就会产生一个页面异常。在异常处理函数中会将这块虚拟页面映射到它应该映射的物理页面上。

Q:什么是伙伴(buddy)系统?
A:用伙伴算法(一般的数据结构书中都有讲解)管理物理内存的系统。它分配的物理内存大小都是页(4K)的整数倍。

Q:什么是slab分配器?
A:指的是内存管理单元先向伙伴系统申请一块较大的物理内存(批发),然后再将其肢解成许多小碎片分配给需要的进程(零售)。当有的进程需要
分配一小块内存(一般都小于一个页面,或不是页的整数倍),用来存放某个数据结构(如vm_area_struct),都可以向slab申请零售。

Q:什么是足印(footprint)?
A:足印(footprint)是指要完成某个工作,需要访问的缓存(一般指L1 DATA CACHE 或TLB)项的个数。
例如,完成的工作是:访问B. 但要访问B对象首先必须从A对象中获得B的指针,如果A,B在一个页面中,那么只需要在TLB踏上一个"足印"就可以了,
否则需要踏上两个“足印”;进一步的,如果A,B对象在同一个16或者32个字节对齐的空间里,那么在L1 DATA CACHE里只需要踏上一个足印就可以了。
一般完成某项工作在各种缓存上的足印越少,引起缓存失去命中的可能性就越小,缓存和内存之间的交互就越小,因此访问速度就越快。

Q:什么是active_mm?
A:active_mm表示当前与CPU关联的分页结构,对于普通进程,它等于mm,对于内核线程,它等于上一次用户进程的mm。

Q:什么是e820?
A:INT15的0xe820(=AX)号BIOS调用获取系统物理内存的配置表(e820map)。

......待续!

由于小弟水平有限,有什么不足之处,敬请指正!

Q:源代码中的gfp_xxx,gfp是什么的缩写?
A:是Get Free Page。
-- zeuszj

Q:cache_cache里的slab的大小是不是一个page?
A:cache_cache是专用slab管理器队列的头,在 kmem_cache_sizes_init() 的过程中cache_cache->gfporder应该一直都是0,所以是一个page;而这个队列中的各个slab管理器(kmem_cache_t)的gfporder都不一定等于0,所以不一定是一个page。

Q:kmalloc(size)返回的是物理地址,还是虚拟地址,为什么?
A:是虚拟地址。因为该地址是经过映射后的地址。
-- ytang

Q:怎样得到kmalloc分配的内存地址的实际物理地址?
A:kmalloc分配了一段物理上连续的内存空间,可以通过virt_to_phys()将返回的虚地址转换为一个物理地址,或者通过virt_to_bus() 转换为一个IO总线地址。
--jkl

Q:malloc()在内核中对应的函数是什么?
A:用户程序中使用的malloc是Glibc包装过的函数,它通过brk系统调用分配虚存给用户。
--xshell

Q:分配虚存空间有了mmap和munmap为什么还需要sys_brk?
A:其实,brk调用的系统调用是sys_brk,他通过mmap进行实现(可以这样认为)。但是,对于用户调用的malloc,free等函数,是由glibc实现的。即:库首先通过brk向系统申请一块大的虚存块,然后,这块内存由库进行管理,就是堆的管理由库实现。实际上,调用brk的目的无非是告诉内核这块内存的引用是合法,只有这样,缺页中断才能进行下去。如果没有这种机制,则可能导致应用程序对应的虚存块太多,使系统性能不佳。如果堆的管理在应用层进行,则没有这种坏处。
-- xiongjs

Q:请教一个术语--“堆”。
A:堆和栈合起来才是堆栈,堆是从低到高扩展的,栈是从高到低扩展的。局部变量都在栈里,通过malloc分配的内存都是在堆里的。

Q:malloc在程序结束不free会怎样?
A:进程退出后,与进程相关的所有资源都被内核无条件释放,进程一般不会在内核中造成资源溢漏。
malloc()基于进程的虚存映射区域,进程退出后,随着虚存映射的撤消,它所占用的物理页面也随之释放。

A:page->age与__PAGE_OLD标志位有何关系?
Q:和交换有关。
PAGE_OLD实际上是cpu自己设定的,每次被访问的页面会被cpu设为~PAGE_OLD,age是linux设定的,初始根据PAGE_OLD,然后不断改动。
--lucian_yao

A:我想阅读mm部分的源代码,从哪个函数入手?
Q:page_alloc.c和slab.c是内核用于分配内存的,可以先看。
--lucian_yao

......待续!


1)

Q:内核启动相关的代码有哪些?

A:以X86为例,

arch/i386/boot/bootsect.S 引导部分;

arch/i386/boot/setup.S,video.S 根据BIOS初始化硬件数据,进入保护模式,并加载内核映象;

arch/i386/kernelhead.S 页表初始化;

2)

Q:内核引导时可以加参数麽?有哪些参数可以加载?

A:可以.一般而言,就是在lilo引导指定内核时加参数,如root=/dev/hda??,参见

BootPrompt-Howto.

3)

Q:内核引导过程中为什么不能使用0-64K直接的地址区域?

A:保留给BIOS数据区,在启动过程中,启动代码使用BIOS数据区和相关的BIOS调用获取初始化必

需的硬件信息.但是在启动后期该区域可以被覆盖使用,这也就意味着内核启动之后不能够进行BIO
S

调用.

4)

Q:大内核与普通内核的分界线是多少K?

A:大小在508K之内的属于普通内核,可以直接加载到0x10000,然后解压缩到0x100000,否则加载到

0x100000后再原地解压.

5)

Q:508K数值是如何得到的?

A:

内核引导代码将自己从当前所在的位置0x7c00:0000跳到0x9000:0000处(即576K地址处)

继续运行.所以如果是xx普通内核则必然要求大小满足

576K - 64K(BIOS自动保留区) - 参数区4K(到底存放了什么有待商榷) = 508K 之内.

参数区存放系统引导时接收的命令行参数和BIOS传给内核的必要的硬件信息

6)

Q:如何编译链接不同类型的内核映象?

A:make bzimage与make zimage分别对应了大内核与普通内核的生成方式.

7)

Q:内核启动时传入的命令行参数存放在甚么位置?

A: ?????

8)

Q:内核启动初始时的内存如何布局?

A:

0A0000 +------------------------------+

| Reserved for BIOS | Do not use. Reserved for BIOS EBDA.

09A000 +------------------------------+

| Stack/heap/cmdline | For use by the kernel real-mode code.

098000 +------------------------------+

| Kernel setup | The kernel real-mode code.

090200 +------------------------------+

| Kernel boot sector | The kernel legacy boot sector.

090000 +------------------------------+

| Protected-mode kernel | The bulk of the kernel image.

010000 +------------------------------+

| Boot loader | <- Boot sector entry point 0000:7C00

001000 +------------------------------+

| Reserved for MBR/BIOS |

000800 +------------------------------+

| Typically used by MBR |

000600 +------------------------------+

| BIOS use only |

000000 +------------------------------+

ps,我在版面上找了找,没有发现可以作为FAQ的好帖子,以上是自己看启动部分并

查阅一些网络资料根据自己的理解给出的几篇FAQ,敬请各位批正与补充.

网络上有英文的可以参考的关于启动部分的FAQ么?哪位知道的话,给个链接,我可以

翻译几篇充实一下这一部分的FAQ内容.

to garycao,我下一部分将整理7. 内核模块的FAQ

Linux 内核编程

1. Q: linux 内核原代码汇编中 .align 伪指令的意思是什么?

```A: (rush)gas文档
```For example `.align 3' advances the location counter until it a
multiple of 8. If the location counter is already a multiple of 8, no
change is needed.
```比如.align 3,2的三次方就是8,也就是要对齐在8边界,比如你现在所在的byte是5,那.align 3之后那个变量就会在8,中间自动插了2个内容为null的byte。如果是在程序代码段中则会插入nop操作码,如果我没理解错的话。

2. Q: start_kernel里面的prof_shift干什么用的 ?

if (prof_shift) {

prof_buffer = (unsigned int *) memory_start;

/* only text is profiled */

prof_len = (unsigned long) &_etext - (unsigned long) &_stext;

prof_len >>= prof_shift;

memory_start += prof_len * sizeof(unsigned int);

memset(prof_buffer, 0, prof_len * sizeof(unsigned int));

}

prof_buffer分配做什么用的,prof在原代码里什么意思

```A: (xshell)prof means profile,也许译成"概要"比较合适,这里是内核对自身代码使用情况的一个统计

这段代码的意思是你是否想通过在启动命令行中设置profile="整型参数n"将内核分成prof_shift=n个部分以便检查内核各部分代码使用的频繁程度

prof_buffer当然是内核存放那些统计记录的地址区域

init/main.c中该函数用于从命令行接受启动参数profile,赋值给prof_shift

135 static int __init profile_setup(char *str)

136 {

137 int par;

138 if (get_option(&str,&par)) prof_shift = par;

139 return 1;

140 }

与之相关的有/proc/profile and /usr/sbin/readprofile,当然必需在启动时加profile=integer,否则没有的啊

3. Q: System.map中的几个标志T,t,B,b,..的问题 ?

```A: (ytang)refer from binutils documents:

The symbol type. At least the following types are used; others are,
as well, depending on the object file format. If lowercase, the symbol
is local; if uppercase, the symbol is global (external).
A

The symbol's value is absolute, and will not be changed by further linking.

B

The symbol is in the uninitialized data section (known as BSS).

C

The symbol is common. Common symbols are uninitialized data. When
linking, multiple common symbols may appear with the same name. If the
symbol is defined anywhere, the common symbols are treated as undefined
references. For more details on common symbols, see the discussion of
-warn-common in Linker options.
D

The symbol is in the initialized data section.

G

The symbol is in an initialized data section for small objects.
Some object file formats permit more efficient access to small data
objects, such as a global int variable as opposed to a large global
array.
I

The symbol is an indirect reference to another symbol. This is a
GNU extension to the a.out object file format which is rarely used.
N

The symbol is a debugging symbol.

R

The symbol is in a read only data section.

S

The symbol is in an uninitialized data section for small objects.

T

The symbol is in the text (code) section.

U

The symbol is undefined.

V

The symbol is a weak object. When a weak defined symbol is linked
with a normal defined symbol, the normal defined symbol is used with no
error. When a weak undefined symbol is linked and the symbol is not
defined, the value of the weak symbol becomes zero with no error.
W

The symbol is a weak symbol that has not been specifically tagged
as a weak object symbol. When a weak defined symbol is linked with a
normal defined symbol, the normal defined symbol is used with no error.
When a weak undefined symbol is linked and the symbol is not defined,
the value of the weak symbol becomes zero with no error.

4. Q: 为什么需要copy_from_user ?

```A: (xshell)

```1.
copy_from_user中的fixup的作用是为了修补当缺页异常在中断上下文中发生时保证copy_from_user的正常返回,其返回值为尚
未成功copy的字节数,如果在非中断上下文的情况下,发生用户空间或内核空间地址缺页异常仍然按照一般的缺页异常的处理方式调页.所以
copy_from_user在使用上具有通用性
```2. 内核地址空间中可以发生缺页异常,但是并不真正地调页,这仅仅是为了遵循MMU的缺页机制而已,同时也做一些缺页检查,这一点可以在fault.c中的do_page_fault()的vmalloc_fault:中找到答案

5. Q: wmb是干吗的函数 ?

```A: (xshell)在指令序列中放一个wmb的效果是使得指令执行到该处时,把所有缓存的数据写到该写的地方,同时使得wmb前面的写指令一定会在wmb的写指令之前执行

6. Q: 宏#与##有什么区别 ?

```A: (jkl)宏定义中的"#"前缀将参数替换成字符串,例如

#define test(x) #x

test(123) 被替换成字符串"123";

"##"用于连接参数,例如

#define test(x,y) ##x##y

test(123,456) 替换成123456;

因此BI(0x0,0)替换成BUILD_IRQ(0x00),"pushl $"#nr"-256\n\t"替换成"pushl $""0x00""-256\n\t"

cpp.info手册对此有详细说明。

7. Q: __attribute__是什么意思?

```A: (jkl)__attribute__是gcc的关键字,用以描述变量属性,如:

__attribute__((regparm(0))) int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1,

内核调试
1. Q: 有人熟悉linux内核调试技术吗?
```A: (garycao)有以下几种方法:

  • 使用kgdb通过串口来调试
  • bdi2000 gdb可以通过以太(bdi2000的以太,bdi2000通过bdm或jtag来调)来调.(注:x86没有bdm和jtag调试接口)
  • windriver vision probe(click)来调试内核,最大的不方便是看不到源码,不过如果你熟悉汇编的话,也能调.

2)));禁止printk使用寄存器传递调用参数,并将printk的参数1作为printf格式串,从参数2开始检查其类型;详细信息

8. Q: 请问_end在那儿定义的 ?

(2.0.34里的arch\i386\kernel\setup.c中的_end变量line number 162)

```A: (jkl)_end是连接器ld定义的,每个ELF格式的应用程序都可以使用此符号。参见vmlinux.lds文件.

```ld的脚本里面可以定义许多东西。info ld可以了解ld脚本的编写。

9. Q: .prvious是什么意思 ?

```A: (jkl).previous伪指令恢复当前段的前一个段作为当前段,由于ELF中允许用.section自定义段,这里的.previous作用就是恢复.text作为当前段。

```或许应该说恢复到当前.section定义之前的段作为当前段。

10. Q: volatile是什么意思 ?

````A: (onfirelinux)volatile指一个变量可能随时由于外界地变化而变化。详细信息

11. Q: 什么是信号 ?

````A: (sirx)信号是UNIX进程间通信的一种标准方式,在最早期的UNIX系统中已经存在。信号的出现允许内核和其它进程通知进程特定事件的发生。现代UNIX中也存在其它的进程间通信方式,但由于信号相对简单和有效,它们仍然被广泛使用。 详细信息



硬件相关
1. Q: 磁盘扇区与磁盘块如何定义以及如何区分使用?
```A: (m.ouyang)Basically I think, hard sector is a physical parameter got from device, block size is just block size, when fs layer transfers requests to ide drivers , all info are in sector expression, anyway, block size setting will affect io requests. For example, if you doubled block size, you may cut io request times(ide interrupts) to nearly a half. So in your own ide/atapi driver, you can define the block size as you want, but not sector size, only keep it as multiples of sector size.

网络
1. Q: 怎样才能快速找到connect,socket函数实现的代码?
```A: (nxin)下载并解开glibc的源码,socket的实现在sysdeps/unix/sysv/linux/i386/socket.S中, linux的大部分系统调用都在sysdeps/unix/sysv/linux/ 或sysdeps/unix/sysv/linux/i386/ 中。系统调用最后都调用了int $0x80,有些共用同一个入口,比如socket,connect都调sys_socketcall,但select调sys_select。
2. Q: 请教高手:Lan网卡收到包后,应该比较mac地址?
```A: (nxin)网卡可以工作在几种模式之下,比如是否接收广播,是否接收指定MAC地址,是否接收指定多播地址,是否全部接收,一般情况不设为全部接收状态,因为这样会加重系统负担,如果你需要可以设为混杂模式就可以全部接收了。

进程管理及线程相关
1. Q: 如何在内核中唤醒和睡眠用户进程?
```A: (xshell)你可以参考interruptible_sleep_on和wake_up_interruptible的代码实现对指定进程的睡眠与唤醒,
其中,使用interruptible_sleep_on将当前进程置入睡眠态和一睡眠进程管理队列中,该队列中的进程可被中断唤醒,wake_up_interruptible则唤醒睡眠进程管理队列中的进程。 详细信息

2. Q: 如read, 用户没输入时候,系统调用阻塞。此时候进程(进程1)是否退出了核心执行态,进入suspend,由内核重新调度其他进程(进程2)运行;那先前的进程1在用户输入时如何又再次获得cpu呢??是等进程2 的时间片用完,重新调度吗 ?
```A: (linux_tao)进程在核心态执行系统调用,系统调用阻塞时进程转入内存睡眠状态,内核调度其他进程运行。当睡眠进程等待的事件发生时,该进程被唤醒,转为内存就绪。之后它被调度,进入“核心态运行”状态。在此状态下,继续完成read调用。read调用完成后,返回用户态运行。
```(sirx)不需要等到进程2的时间片用完。如果进程1等待的中断发生的时候进程2正在执行系统调用,那么需要__等到进程2的系统调用执行完__再重新调度。如果中断发生的时候进程2正在用户态运行,马上重新调度。 详见Linux 内核笔记2 – 进程调度

3. Q: linux中线程是不是属于内核实现的?或者是创建线程在用户级,管理在内核?
```A: (sirx)linux下的线程有用户态和内核态两种,但内核只创建和管理内核线程,用它们来完成一些需要经常重复执行的工作。用户线程,就是应用程序内部的线程啦,由用户态的线程库来生成和调度,内核从来就不知道用户线程的存在。

4. Q: 在linux下当一个进程创建了若干个线程的时候
a、这时在主进程(非线程中)内调用fork,那么子进程是如何继承父进程的线程的?是全部还是不继承?
b、若在主进程的某个线程内fork,这时这个子进程是继承父进程的全部线程还是只继承fork它的线程或是不继承?
```A: (待答)

5. Q.在当前系统下,调度时间片的长度是多少?
```A: (sirx) 与2.2.x版的内核相比,kernel2.4.x的时间片长度缩短了,对于最高优先级的进程来说,时间片的长度为100ms,默认优先级进程的时间片长度为60ms,而最低优先级进程的时间片长度为10ms。

6. Q. Linux如何保证对I/O事件相对比较快的响应速度,这个响应速度是否与调度时间片的长短有关?
```A: (sirx)当I/O事件发生的是时候,对应的中断处理程序被激活,当它发现有进程在等待这个I/O事件的时候,它会激活等待进程,并且设置当前正在执行进程的need_resched标志,这样在中断处理程序返回的时候,调度程序被激活,原来在等待I/O事件的进程(很可能)获得执行权,从而保证了对 I/O事件的相对快速响应(毫秒级)。
从上面的说明可以看出,在I/O事件发生的时候,I/O事件的处理进程会抢占当前进程,响应速度与调度时间片的长度无关。

7. Q.高优先级(nice)进程和低优先级进程在执行上有何区别?例如一个优先级为-19(最高优先级)的进程和优先级为20(最低)的进程有何区别
```A: (sirx)进程获得的CPU时间的绝对数目取决于它的初始counter值,初始的counter的计算公式(sched.c in kernel 2.4.14)如下:
p->counter = (p->counter >> 1) + ((20 - p->nice) >> 2) +1)
由公式可以计算出,对于标准进程(p->nice 为0), 得到的初始counter为6,即进程获得的时间片为60ms。
最高优先级进程(nice为-19)的初始counter值为10,进程的时间片为100ms。
最低优先级进程(nice为20)的初始counter值为1,进程时间片为10ms。
结论是最高优先级进程会获得最低优先级进程10倍的执行时间,普通优先级进程接近两倍的执行时间。当然,这是在进程不进行任何IO操作的时候的数据,在有IO操作的时候,进程会经常被迫睡眠来等待IO操作的完成,真正所占用的CPU时间是很难比较的。
我们可以看到每次重新计算counter的时候,新的counter值都要加上它本身剩余值的一半,这种奖励只适用于通过SCHED_YIELD 主动放弃CPU的进程,只有它在重新计算的时候counter值没有用完,所以在计算后counter值会增大,但永远不可能超过20。

8. Q: Linux提供的同步机制有那些?
```A: (garycao)(see /usr/include/目录下semaphore.h,pthread.h)
一般linux信号量分为以下几类
1. semaphore:
int sem_init (sem_t *sem, int pshared,
unsigned int value);
int sem_wait (sem_t * sem);
int sem_post (sem_t * sem);
int sem_destroy (sem_t * sem);

2. mutex
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_unlock
pthread_mutex_destroy

3.Condition Variables
pthread_cond_init
pthread_cond_wait
pthread_cond_signal
pthread_cond_broadcast
pthread_cond_destroy


内核同步
1. Q: 对于单cpu的系统,是不是不应该用spin_lock。如果用了,会不会降低系统的性能呢?
```A: (minihorse)
> I have a question related to spin locking on UP systems.Before that I would
> like to point out my understanding of the background stuff
> 1. spinlocks shud be used in intr handlers
It should be used in the interrupt handler, if you need to prevent any race
conditions with other interrupt/non-interrupt context code that may be
executing on some other CPU on an SMP system. Thus spinlocks need to be held
for as short a duration as possible. You would need to use the
spin_lock_irqsave/spin_unlock_irqrestore variant pair to prevent your
interrupt handler from running on the same processor while holding the lock.
This may be needed if the interrupt handler may try to acquire the same lock
thus causing a deadlock.
> 2. interrupts can preempt kernel code
> 3. spinlocks are turned to empty when kernel is compiled without SMP
> support.
>
> If a particular driver is running( not the intr handler part) and at this
> time an interrupt occurs. The handler has to be invoked now. Won't the
> preemption cause race conditions/inconsistencies? Is any other mechanism
> used? Pl correct me if I have not understood any part of this correctly
On a UP kernel the spin_lock_irqsave/spin_unlock_irqrestore pair expand to
save_flags(flag); cli()/restore_flags(flag).
The masking of interrupts on the processor between spin_lock_irqsave and
spin_unlock_irqrestore pair prevent the user context code from being
preempted by the interrupt handler.

进程管理及线程相关
>>>2. Q: 如read, 用户没输入时候,系统调用阻塞。此时候进程(进程1)是否退出了核心执行态,进入suspend,由内核重新调度其他进程(进程2)运行;那先前的进程1 在用户输入时如何又再次获得cpu呢??是等进程2 的时间片用完,重新调度吗 ?
>>>```A: (linux_tao)进程在核心态执行系统调用,系统调用阻塞时进程转入内存睡眠状态,内核调度其他进程运行。当睡眠进程等待的事件发生时,该进程被唤醒,转为内存就绪。之后它被调度,进入“核心态运行”状态。在此状态下,继续完成read调用。read调用完成后,返回用户态运行。

补充一点:
>>>是等进程2 的时间片用完,重新调度吗 ?
不需要等到进程2的时间片用完。如果进程1等待的中断发生的时候进程2正在执行系统调用,那么需要__等到进程2的系统调用执行完__再重新调度。如果中断发生的时候进程2正在用户态运行,马上重新调度。
---老王开始卖瓜:
俺前几天写的一篇文章有更详细的相关内容:
<< Linux 内核笔记2 – 进程调度 >>
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=294463&page=1&view=collapsed&sb=5&o=7&fpart=

>>>3. Q: linux中线程是不是属于内核实现的?或者是创建线程在用户级,管理在内核?
>>>```A: (待答)

A. linux下的线程有用户态和内核态两种,但内核只创建和管理内核线程,用它们来完成一些需要经常重复执行的工作。用户线程,就是应用程序内部的线程啦,由用户态的线程库来生成和调度,内核从来就不知道用户线程的存在。

相关阅读 更多 +
排行榜 更多 +
步行僵尸2无限金币版

步行僵尸2无限金币版

体育竞技 下载
狐狸一号特殊任务无限金币版

狐狸一号特殊任务无限金币版

体育竞技 下载
忍者之雷复仇无限金币钻石版

忍者之雷复仇无限金币钻石版

体育竞技 下载