《UNIX技术内幕》勘误及问题解答_25

简介: From: quntmec@hotmail.com To: qf.hao@hotmail.com Subject: RE: 关于《UNIX技术内幕》的勘误及遇到的问题_25 Date: Fri, 17 Feb 2012 11:08:10 +0800 郝先生, 对...


From: quntmec@hotmail.com
To: qf.hao@hotmail.com
Subject: RE: 关于《UNIX技术内幕》的勘误及遇到的问题_25
Date: Fri, 17 Feb 2012 11:08:10 +0800

郝先生,

对于问题4中你的回复,我还是有些疑问,具体如下:

----------------------------------

问题4:是这样吗?是否我理解错了?
[郝] :事实上u_osema定义为 Semaphore *u_osema[4],其每个元素都是Semaphore *,且从内核全局semaphs中获得,所以尽管子进程拷贝了父进程的u_osema数据,但是它们都指向同一个
Semaphore指针(如果不为NULL),这样Acquire或者Release还是操作的同一个元素。所以可以实现同步。

-----------------------------------


你 提到“u_osema定义为 Semaphore *u_osema[4],其每个元素都是Semaphore *”,这个我同意。但问题是“Semaphore *”这个指针指向的是一个虚拟地址,而不是物理地址。这也就决定了以后父、子进程所指向的不是同一个元素。代入619页例1,如下:

首先,设定一个Semaphore * res,以记录对应的u_osema[sd]。且假设res本身的地址为0x1000(虚拟地址)

1)在创建子进程之前,第4行:“sd = CreateSemaphore(1);”。父进程已创建了信号量sd。假设 res = u_osema[sd],且假设的 res 所指向的地址为 0x2000。之后,执行fork。

2)假设父进程先执行,则在整个执行过程中,res本身的地址都是0x1000,它所指向的地址都是0x2000,且都在父进程空间里

3) 到了子进程执行时,res本身的地址也是0x1000,它所指向的地址也是0x2000,这些值都是从父进程里复制过来的。但是,这里是子进程空间。虽然 虚拟地址是一样的,但父、子进程所对应的实际物理地址空间是不同的,也就是各自的数据是独立的。因此,父进程里修改了u_osema[父进程的 sd]->s的值,这并不等于子进程里u_osema[子进程的sd]->s这个值被改变。换句话说,u_osema[父进程的sd]和 u_osema[子进程的sd]有相同的虚拟地址(不是物理地址),且指向的目标虚拟地址都是相同的,但由于处于不同的物理空间,因此它们最终指向的数据 是不一致的。

最后,如果要使u_osema[父进程的sd]和u_osema[子进程的sd]都指向相同的变量,则需要对应分配相同的“物理地址”;或者通过内存映射等方式实现指向一致。

以上是我的理解,不知道对不对?

[郝] : 看得出来你对虚拟内存理解的不错,但是有一点要注意:semaphs和u_osema都是在内核空间的,而内核空间只有一份,并一直驻留在内存中,所以 semaphs的地址不会改变(不管是虚拟还是物理)。这样u_osema[sd]中存储的正式semaphs中的元素,也就是 &semaphs[0], &semaphs[1],...,所以只要子进程复制了u_osema[sd]的值,它就会指向同一个地方。





From: qf.hao@hotmail.com
To: quntmec@hotmail.com
Subject: RE: 关于《UNIX技术内幕》的勘误及遇到的问题_25
Date: Fri, 17 Feb 2012 09:13:22 +0800




From: quntmec@hotmail.com
To: qf.hao@hotmail.com
Subject: 关于《UNIX技术内幕》的勘误及遇到的问题_25
Date: Thu, 9 Feb 2012 17:37:16 +0800

郝先生,

613页,有关信号量,我的理解如下:

1、全局结构与数组

(1)struct Semaphore,它是“信号量“的结构体,它的成员解释如下:
s代表信号量;ref代表该信号量总共被多少个进程共享;flag代表该信号量当前的状态

(2)struct Semaphs,它是所有信号量的集合信息,它的成员解释如下:
semas[64]代表系统最多可以同时提供64个信号量;flag代表整个信号量集合的状态,如果是S_WANT,表示64个信号量已分配完,没有空余。

(3)u_osema[4],代表1个进程最多可以同时使用4个信号量,其中每个元素代表1个信号量

(4)u_rsema[4]:问题2

2、函数

(1)AcquireSemaphore(),该函数的主要作用是执行“P操作“。

(2)ReleaseSemphore(),该函数的主要作用是执行“V操作”。



问题1:以上的理解对吗?
[郝] :对,很好!
问题2:u_rsema[4]有什么具体的作用吗?是指获得该信号量(对应u_osema[i])的进程的个数吗(即如果信号量初值不为1的情况,表明可以有多个进程同时获得该信号量)?
[郝]:记录本进程已经获得的信号量, u_rsema[0]记录u_osema[0]的是否获得(>0获得,否则没获得)。
问题3:按照struct Semaphore的定义,所有的信号量都是无名的。再有,整个系统只能同时存在64个信号量,且每个进程最多只能使用其中4个信号量,是这样吗?如果是的话,为何这样设计?
[郝] :是这样的,简单起见,且性能比较好。


3、 619页,应用示例的例1中,第4行:“sd = CreateSemaphore(1);”,可见,在创建子进程之前,父进程已创建了信号量sd,且它的初值为1, 即,u_osema[sd]->s的值为1。在fork之后,父、子进程都各自拥有自己的sd,且初值都是1。

假如父进程先运行, 则执行AcquireSemaphore(sd),即执行“P操作”,这时,u_osema[父进程的sd]->s的值变为0。接着,父进程执行 write操作。假设在write执行完成前,父进程的时间片用完了,系统切换至子进程执行。子进程会首先执行 AcquireSemaphore(sd),即“P操作”。由于父、子进程各自拥有独立的数据空间,因此这时u_osema[子进程的sd]->s 的值仍然为1。可见,”P操作“是会成功的!这显然是不对的!按照程序的本意,父进程的“P操作”应该会阻止子进程对该信号量的获取(即阻止子进程进入临 界区)。

问题4:是这样吗?是否我理解错了?
[郝] :事实上u_osema定义为 Semaphore *u_osema[4],其每个元素都是Semaphore *,且从内核全局semaphs中获得,所以尽管子进程拷贝了父进程的u_osema数据,但是它们都指向同一个
Semaphore指针(如果不为NULL),这样Acquire或者Release还是操作的同一个元素。所以可以实现同步。



此外,勘误,无
[郝]:下一版会考虑多增加说明(包括如上内容)。


Steve



《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
京东
亚马逊                          China pub
上学吧                          1号店

目录
相关文章
|
Unix
和Steve之间的通信--RE: 关于《UNIX技术内幕》的勘误及遇到的问题_10
Steve,mtpi是一个汇编指令,用于在内核模式和用户模式之间传递数据。在第18页有描述From: quntmec@hotmail.comTo: qf.hao@hotmail.comSubject: RE: 关于《UNIX技术内幕》的勘误及遇到的问题_10Date: Sun, 20 Nov 2011 17:01:08 +0800 郝先生,mtpi函数的代码在哪一页?我重新翻阅了一下,除了在第140页处(最后一段)可以找到一点有关mtpi的说明外,我没有发现书里有mtpi的代码。
881 0
|
Unix
和Steve之间的通信--关于《UNIX技术内幕》的勘误及遇到的问题_3
From: quntmec@hotmail.comTo: qf.hao@hotmail.comSubject: 关于《UNIX技术内幕》的勘误及遇到的问题_3Date: Thu, 6 Oct 2011 19:24:10 +0800 郝先生,对于启动模块这一章...
771 0
|
Unix
和Steve之间的通信--RE: 关于《UNIX技术内幕》的勘误及遇到的问题_4
Steve,应该是第2中情况,u变量就是一个user结构体,并且该变量地址固定在0o140000处,其所占空间长度就是结构体的长度。至于为什么要固定地址是0o140000,因为它是第6号虚拟寄存器映射的。
773 0
|
Unix
《返璞归真--UNIX技术内幕》--第14章 多线程的实现
14.1  概述 现代操作系统引入了线程的概念。线程是CPU执行的最小单元,相对于进程而言,它具有轻捷、高效、开销小等优点。 14.2  线程和经典进程的比较 线程和经典进程的主要区别如下。
873 0
|
Unix
《返璞归真--UNIX技术内幕》-- 第11章 UNIX可执行文件
11.1  .out文件 本版UNIX的可执行文件是.out格式,如果你在UNIX下用gcc编译程序,它默认会生成一个名为“a.out”的可执行文件。
889 0
|
Unix
《UNIX技术内幕》--第3章 虚拟内存
Normal 0 false false false MicrosoftInternetExplorer4 /* Style Definitions */ table.
613 0
|
Unix C语言
《返璞归真--UNIX技术内幕》--第6章 中断处理过程
6.4  PDP 11/40的中断类型 系统中的中断主要有下面几种。 6.4.1  电传终端接口输入中断 电传终端接口用于链接PDP 11/40的总线和主要的输入、输出终端,当时该终端是电传打字机,这也是UNIX中用tty(teletypewriter)表示进程所使用的终端类型的原因,事实上电传接口还可以连接彩色显示器(CRT)等。
910 0
|
存储 缓存 Unix
《返璞归真--UNIX技术内幕》--第9章 字符设备驱动
本系统中的输入输出设备都是字符设备,它们包括:KL-11/DL-11A——电传串行接口、PC-11——纸带打孔机和LP-11——行打印机。其中KL-11用于连接终端(terminal),作为用户键盘输入和显示输出的交互接口。
952 0
|
Unix
《返璞归真--UNIX技术内幕》--源代码
本源代码经宁希波帮助整理,去除了''和'&'符号,在此表示诚挚的谢意!源码中除/usr/personal目录外,均由Bell Labs(贝尔实验室)开发。
693 0
|
Unix Linux 调度
《UNIX技术内幕》勘误及问题解答_26
From: quntmec@hotmail.com To: qf.hao@hotmail.com Subject: 关于《UNIX技术内幕》的勘误及遇到的问题_26 Date: Sun, 26 Feb 2012 16:34:18 +0800 郝先生, 线程方面碰到的问题如下: 1、689页,倒数第2、3行,里面提到第14章所实现的线程在退出时只会将线程栈释放、而不会释放该线程所分配的堆空间,这是否会造成内存泄漏?[郝]:如果用户线程在每次调用malloc后,都会调用free来释放它,那么就不会有内存泄漏。
937 0