- 論壇徽章:
- 0
|
本文和[ Unix編程常見問題解答]相比與solaris更加貼近。
同時也算給本版的faq分類起一個借鑒作用。
名稱 -- Unix編程/應(yīng)用問答中文版
版本 -- 0.03 ( 2002-03-06 外發(fā)版 )
維護(hù) -- 小四 <cloudsky@263.net>; or <scz@nsfocus.com>;
主頁 -- http://www.nsfocus.com
創(chuàng)建 -- 2001-02-05 13:49
更新 -- 2002-03-03 17:42
感謝 --
感謝C語言的發(fā)明者、Unix操作系統(tǒng)的發(fā)明者、感謝全世界C程序員創(chuàng)造的Unix共
享傳統(tǒng)文化圈,她是如此強(qiáng)大、充滿禁忌、而又魅力四射。
感謝我的朋友,deepin <deepin@nsfocus.com>;,在整個維護(hù)過程中的支持、幫
助和鼓勵。感謝我所有的NSFocus安全研究小組的朋友(tt、yuange、security@
nsfocus.com ... ...),是他們?nèi)萑涛以谶@個非正業(yè)上花費(fèi)時間。
主要支持人員(字母順序) --
Andrew Gierth <andrew@erlenstar.demon.co.uk>;
backend <backend@nsfocus.com>;
Casper Dik <Casper.Dik@Holland.Sun.COM>;
deepin <deepin@nsfocus.com>;
scz <scz@nsfocus.com>;
suxm <suxm@gnuchina.org>;
tt <warning3@nsfocus.com>;
簡介 --
這份文檔不是FAQ(Frequently Answered Question),不少問題屬于FUQ(Freque-
ntly Unanswered Question)。換句話說,不一定是最常見的編程、應(yīng)用問答,很可
能其中的答案尚是一個構(gòu)思,還沒有成為現(xiàn)實(shí),又或者根本是個錯誤的思想火花。但
是,她的確在試圖回答一些很有意義的問題,讓更多的Unix/C程序員、系統(tǒng)管理員共
享彼此的智慧,那是三十年前無數(shù)前輩精英做到過的,也是我們正試圖做到的。
Q -- Question
A -- Answer
D -- Discuss
聲明 --
永久拒絕任何商業(yè)性質(zhì)的轉(zhuǎn)載、摘錄、引用。在不對所有文字做任何修正的前提
下,允許一切教育性質(zhì)的轉(zhuǎn)載、摘錄、引用,無須提前知會維護(hù)者(就是me,faint)。
一旦出現(xiàn)需要修正文字的情況,只能通過維護(hù)者修正。維護(hù)者會在下一次版本升級過
程中正式增加這種修正,保留提供修正者應(yīng)有信息。同時意味著提供修正者永久自愿
放棄商業(yè)性質(zhì)的所有權(quán)益。不接受這種條件的提供修正者,務(wù)必提前知會維護(hù)者,此
類修正將不出現(xiàn)在下一次版本升級中。
文中所附各種源代碼,在嚴(yán)格意義上可能存在版權(quán)問題,所以事實(shí)上這份文檔帶
有"半地下"性質(zhì),使用者務(wù)必自己小心卷入此類糾紛。
文中技術(shù)可能涉及未公開的、未文檔化的、非規(guī)范的編程、應(yīng)用接口,文檔提供
的重在思想,而不保證是正確、高效、唯一的解答。
維護(hù)者不對文中任何技術(shù)引起的任何災(zāi)難性后果負(fù)任何法律上的、道義上的責(zé)任。
Ok, Let's go.
輔助說明 --
2002-03-06 12:14
輔助說明只在"外發(fā)版"中存在,稍微解釋一下。
一直沒有單獨(dú)出一份完整的,原因很多。如果擱在1995/1996/1997時的CERNET,
這些原因都不成為原因,現(xiàn)在成為原因。不想多說為什么,明白的自然明白,不
明白的當(dāng)我白癡好了,反正別問我。
出于"聲明"中的某些理由,不能在單份完整文檔中附帶可能會帶來麻煩的文字、
代碼,比如Solaris libproc編程接口。但是,在散篇中你能找到它們。如果你
愿意,可以自己將散篇收回到該文檔中,這將與我無關(guān)。一切索要?dú)埲辈糠值泥]
件概不回復(fù)。
本份文檔的絕大多數(shù)內(nèi)容在"中國教育科研網(wǎng)華南地區(qū)網(wǎng)絡(luò)中心BBS"(bbs.gznet.
edu.cn)的Solaris版發(fā)布過了,包括下面處理掉的目錄列表。是該版前版主CPU
師兄當(dāng)年的風(fēng)范促使我開始整理這份文檔的,當(dāng)還昔日指教之情誼。
該份文檔"允許一切教育性質(zhì)的自由轉(zhuǎn)載、摘錄、引用,無須提前知會維護(hù)者"。
我也只是義務(wù)維護(hù)一下,不對本文檔擁有任何權(quán)益。如果不幸潛在擁有而踐踏了
某種信念,在你看到該輔助說明的同時,我將自動放棄這種潛在可能擁有的權(quán)益。
同時意味著一切因本文檔帶來的麻煩,將由你個人承擔(dān)。
既然來自Unix共享傳統(tǒng)文化圈,就讓它徹底回到Unix共享傳統(tǒng)文化圈中去吧。
歡迎一切建設(shè)性的、非索要性質(zhì)的Email交流。
--------------------------------------------------------------------------
目錄
0. Unix/C傳奇問題
0.1 Dennis Ritchie 和 Ken Thompson
0.2 W. Richard Stevens 之死
1. 系統(tǒng)管理配置問題
1.1 如何給SUN工作站增加eeprom硬件口令保護(hù)
1.2 如何增加交換空間
1.3 為什么我不能在/home目錄下創(chuàng)建子目錄
1.4 如何改變一臺主機(jī)的locale
1.5 Solaris 7自動注銷
1.6 一個目錄擁有setgid設(shè)置,怎么理解
1.7 非Sun Console上有無等價Stop-A的按鍵
1.8 如何讓一個用戶只能ftp而無法telnet
1.9
1.10 為什么Sun工作站非要輸入boot命令才能啟動
1.11 如何讓Solaris識別新增加的硬件
1.12
2. 堆棧相關(guān)問題
2.1 如何理解pstack的輸出信息
2.2
2.3 Solaris中如何獲取一個C程序的調(diào)用;厮
2.4 如何編程獲取棧底地址
2.5 如何得到一個運(yùn)行中進(jìn)程的內(nèi)存映像
2.6 調(diào)試器如何工作的
2.7 x86/Linux上如何處理SIGFPE信號
3. -lelf、-lkvm、-lkstat相關(guān)問題
3.1 如何判斷可執(zhí)行文件是否攜帶了調(diào)試信息
3.2 mprotect如何用
3.3 mmap如何用
3.4 getrusage如何用
3.5 setitimer如何用
4. 系統(tǒng)資源相關(guān)問題
4.1 主流Unix操作系統(tǒng)上如何編程獲取進(jìn)程的內(nèi)存、CPU利用狀況
4.2 Solaris下如何獲知CPU速率
4.3 如何編程獲取Solaris系統(tǒng)當(dāng)前內(nèi)存大小
5. 塊設(shè)備相關(guān)問題
5.1 CDROM設(shè)備究竟在哪里
5.2 如何彈出光驅(qū)
5.3 如何利用超級塊進(jìn)行恢復(fù)工作
5.4 Solaris Root口令忘記了
5.5 如何使用fmthard
5.6 如何從光盤恢復(fù)Solaris 7的引導(dǎo)扇區(qū)
5.7 Solaris支持類似微軟autorun.inf文件的功能嗎
5.8 如何修改/dev/null的屬性
5.9
5.10 如何自己制作Solaris啟動軟盤
5.11 x86/Solaris如何訪問FAT32分區(qū)
6. /etc/system可調(diào)資源限制
6.1 Solaris下如何限制每個用戶可擁有的最大進(jìn)程數(shù)
6.2 如何配置系統(tǒng)使之支持更多的偽終端
6.3 如何增加每個進(jìn)程可打開文件句柄數(shù)
6.4
6.5 做了setuid()這類調(diào)用的程序如何產(chǎn)生core dump
6.6 消息隊(duì)列調(diào)整
7. DNS相關(guān)問題
7.1 如何進(jìn)行DNS區(qū)傳輸
7.2 如何獲知權(quán)威名字服務(wù)器
7.3 如何配置DNS的委托解析
7.4 如何獲知BIND的版本號
7.5 Solaris/FreeBSD/Linux如何指定域名解析的順序
8. Solaris內(nèi)核編程相關(guān)問題
8.1 Solaris內(nèi)核模塊中如何getcwd
8.2
8.3 如何避免一個套接字進(jìn)入TIME_WAIT狀態(tài)
8.4 結(jié)構(gòu)在優(yōu)化編譯中的對齊問題
8.5
8.6 如何得到非局部變量列表
8.7
8.8 如何單獨(dú)獲得Solaris編譯環(huán)境
8.9 如何獲取Solaris內(nèi)核可調(diào)參數(shù)列表
8.10
8.11 如何頁邊界對齊式分配內(nèi)存
8.12
8.13 compile()和step()怎么用
8.14
8.15
8.16
8.17
9. 圖形界面相關(guān)問題
9.1 如何避免進(jìn)入Solaris的圖形界面
9.2 Solaris 7的鎖屏
9.3 如何調(diào)整鍵盤重復(fù)率
9.4 如何拔掉鍵盤繼續(xù)運(yùn)行Solaris
9.5 Solaris下如何設(shè)置顯卡分辨率
9.6 Solaris下如何設(shè)置顯示刷新率
10. 網(wǎng)卡相關(guān)問題
10.1 如何在程序中獲取本機(jī)MAC地址
10.2 如何在Sun工作站上安裝3塊網(wǎng)卡
10.3 如何在Solaris x86上安裝網(wǎng)卡驅(qū)動
10.4 Solaris 單網(wǎng)卡多IP(以太網(wǎng)卡別名)
10.5 如何修改主機(jī)名(hostname)
10.6 SPARC/Solaris 2.5/2.6/7/8下如何設(shè)置網(wǎng)卡100Mb全雙工
10.7 Unix/Linux/BSD如何對抗ARP欺騙攻擊
10.8
10.9
10.10
10.11 x86/Solaris如何強(qiáng)制設(shè)定網(wǎng)卡速率
10.12 Solaris/FreeBSD/Linux如何確定網(wǎng)卡Capability/Speed
10.13
10.14 traceroute是怎么實(shí)現(xiàn)的
11. package相關(guān)問題
11.1 Solaris下如何將二進(jìn)制軟件包安裝到指定目標(biāo)路徑下
11.2 Solaris下如何自己定制二進(jìn)制安裝包
11.3 如何恢復(fù)/usr/bin/su的缺省安裝屬性
11.4 如何獲知指定包與其他包之間的依賴關(guān)系
11.5 Linux中如何知道ifconfig屬于哪個包
11.6 Solaris下如何知道某包中有哪些文件
12. 日志相關(guān)問題
12.1
12.2
12.3 如何關(guān)閉cron的日志
12.4
13. 進(jìn)程相關(guān)問題
13.1 如何根據(jù)進(jìn)程名獲得PID
13.2
13.3
13.4 Solaris 7/8下ps輸出中的問號
13.5
13.6
13.7 給定一個PID,如何知道它對應(yīng)一個運(yùn)行中的進(jìn)程
13.8 Unix/Linux編程中所謂"僵尸進(jìn)程"指什么
13.9 x86/FreeBSD 4.3-RELEASE的ptrace(2)手冊頁
13.10 Solaris下如何知道哪個進(jìn)程使用了哪個端口
13.11 x86/FreeBSD如何快速獲取指定用戶擁有的進(jìn)程數(shù)
14. 一些小工具的使用
14.1
14.2
14.3 只在本地文件系統(tǒng)上查找
14.4
15. 32-bit/64-bit相關(guān)問題
15.1 Solaris下如何識別當(dāng)前內(nèi)核版本
15.2 如何啟動Solaris 32-bit/64-bit內(nèi)核
15.3 gcc支持64-bit編譯嗎
15.4 Solaris啟動時內(nèi)核文件找不到了
15.5 64-bit驅(qū)動程序無法在8下關(guān)聯(lián),但在7下工作正常
16. 庫相關(guān)問題
16.1 在Solaris 7下編寫網(wǎng)絡(luò)程序需要鏈接哪些庫
16.2
16.3 鏈接過程中庫的順序
16.4
16.5
16.6 /usr/lib/ld.so.1損壞或丟失
16.7
16.8
16.9 Solaris 8下如何配置運(yùn)行時鏈接環(huán)境
17. 文件查看問題
17.1 如何直接查看man文件
17.2 .tex文件怎么讀
17.3 Solaris下怎么看.ps文件
18. 補(bǔ)丁相關(guān)問題
18.1 如何根據(jù)補(bǔ)丁號從Sun主站下載補(bǔ)丁
18.2
18.3
18.4 給Solaris 2.6安裝推薦補(bǔ)丁集
18.5 已知補(bǔ)丁號,如何最快判斷系統(tǒng)中是否已經(jīng)安裝該補(bǔ)丁
18.6 如何安裝補(bǔ)丁
19. 終端相關(guān)問題
19.1 如何使Backspace鍵做刪除操作,而不是顯示^H
19.2
19.3 如何清空stdin的緩沖
19.4 Linux Console下一按錯鍵就叫,怎么關(guān)
20. shell script問題
20.1 如何獲取一個字符串的長度
20.2 讀超時自動使用缺省值
20.3
20.4 BASH中如何得到一個字符串的子串
20.5
20.6
20.7
20.8 使用tr命令加密文件
20.9 有哪些命令用于查找定位
20.10
20.11 如何將大寫文件名轉(zhuǎn)換為小寫文件名
21. FreeBSD相關(guān)問題
21.1
21.2 如何將一個512字節(jié)的文件寫入主引導(dǎo)扇區(qū)
21.3
21.4
21.5
21.6 x86/FreeBSD 4.x下不能cp覆蓋/kernel
21.7 x86/FreeBSD下如何設(shè)置路由
21.8
21.9 什么是locale
21.10 用cvsup安裝vim
21.11 FreeBSD下vi輸入中文會顯示\x??\x??
21.12
21.13
21.14
21.15 UDMA ICRC error是什么意思
21.16 Limiting closed port RST response什么意思
21.17
21.18
21.19
21.20
22. Linux Kernel Programming
22.1 直接訪問內(nèi)存[顯存]地址
22.2
23. Linux相關(guān)問題
23.1
--------------------------------------------------------------------------
0. Unix/C傳奇問題
0.1 Dennis Ritchie 和 Ken Thompson
Q: 我想知道他們,為什么大家不斷提到這兩個名字?
A: All of Unix Programmers
我們也想知道,
1969年Dennis Ritchie 和 Ken Thompson在貝爾實(shí)驗(yàn)室創(chuàng)造性地發(fā)明了Unix操作系統(tǒng),
為此1983年他們獲得了圖靈獎。
盡管Ritchie是C程序設(shè)計(jì)語言的發(fā)明者,但是他最喜歡的編程語言是Alef。而
Thompson是一名業(yè)余飛行員,曾到莫斯科駕駛過米格-29。
歡迎訪問
http://cm.bell-labs.com/who/dmr/
http://cm.bell-labs.com/who/ken/
0.2 W. Richard Stevens 之死
Q: David Johns <odin@gte.net>;
我是他的崇拜者,用www.google.com搜索他的訃告,但這份訃告沒有提及死因,有人
知道嗎?
真地僅僅是英年早逝嗎?
A: Nithyanandham <m.nithyanandham@blr.spcnl.co.in>;
他死于1999/09/01,家人不想讓別人知道死因。訃告位于
http://www.azstarnet.com/clips/richard_stevens.html
A: joe broz <jbroz@transarc.ibm.com>;
似乎是一場攀巖事故,或者滑雪事故,我不確認(rèn)。
1. 系統(tǒng)管理配置問題
1.1 如何給SUN工作站增加eeprom硬件口令保護(hù)
A: scz <scz@nsfocus.com>;
man -s 1M eeprom了解細(xì)節(jié),要求當(dāng)前是root身份
# /usr/sbin/eeprom (顯示當(dāng)前eeprom配置)
# /usr/sbin/eeprom security-mode=full ( 可選的有command, full, none)
此時進(jìn)入交互式設(shè)置口令過程,總共輸入兩次,如果兩次口令輸入不一致,則本次設(shè)
置作廢。成功設(shè)置之后除了go命令之外的其他ok狀態(tài)下命令均需要口令,包括boot命
令。
設(shè)置成command時,同樣進(jìn)入交互式口令輸入過程。此時,除了boot和go命令之外的
其他ok狀態(tài)下命令均需要口令。注意,如果僅僅輸入boot命令,不需要口令,一旦
boot命令后面帶了參數(shù),比如boot cdrom -s,同樣需要輸入口令。
如果設(shè)置成none(缺省設(shè)置),表示去掉這種口令保護(hù)。
# /usr/sbin/eeprom security-password= (等號后面無其他字符,直接回車)
如果想改變前面設(shè)置的口令,用這條命令,同樣是交互式輸入過程。
# /usr/sbin/eeprom security-#badlogins=3 (缺省是0)
設(shè)置口令輸入嘗試次數(shù)。
警告:如果設(shè)置了eeprom硬件保護(hù)口令而又忘記,會帶來很多麻煩,務(wù)必小心。
一個可行的設(shè)置辦法是,安全模式設(shè)置到command而不是full,這樣至少可以正常啟
動系統(tǒng)。于是只要記得root口令或者還有其他機(jī)會獲得root權(quán)限(緩沖區(qū)溢出?),就
可以通過設(shè)置安全模式為none而挽救回來。
但是如果設(shè)置成full模式卻忘記了eeprom口令,我想首先應(yīng)該打電話給SUN的技術(shù)支
持。如果出于某種理由你不想這樣做,我不確認(rèn)eeprom是否可以熱插拔,先用一個無
口令保護(hù)的eeprom啟動系統(tǒng),然后熱插拔換上那個有口令保護(hù)的eeprom,然后用root
權(quán)限抹去eeprom口令。
1.2 如何增加交換空間
A: WT <wt@server.domain.top>;
你無法改變分區(qū)大小,但是可以增加/刪除交換文件,效果類似交換分區(qū)。下列命令
在根目錄下創(chuàng)建一個500MB的交換文件,名為swapfile
# mkfile 500m /swapfile
下列命令將使之生效
# swap -a /swapfile
現(xiàn)在你有了額外的500MB交換空間,為了每次重啟后依舊有效,編輯/etc/vfstab文件
增加如下行
/swapfile - - swap - no -
# swap -l
這里"-l"意味著"list",顯示所有交換空間。仔細(xì)閱讀"swap"和"mkfile"的手冊頁。
1.3 為什么我不能在/home目錄下創(chuàng)建子目錄
Q: Solaris 7下,root身份,當(dāng)我試圖在/home目錄下創(chuàng)建子目錄時,系統(tǒng)拒絕,為
什么?
A: mohansundarraj
如果/etc/rc2.d/S74autofs腳本中automount(1M)守護(hù)進(jìn)程已經(jīng)mount了/home,就是
這種現(xiàn)象,而這還是缺省安裝后的情形。可以
# /etc/init.d/autofs stop
# umount /home
然后你就可以用root身份在/home下創(chuàng)建子目錄,增加文件了。為了永久取消autofs
特性,可以將/etc/rc2.d/S74autofs腳本改名,并注釋掉/etc/auto_home、
/etc/auto_master兩個文件中的入口點(diǎn)。
SPARC/Solaris的缺省用戶主目錄是/export/home,而不是/home。
1.4 如何改變一臺主機(jī)的locale
Q: 一臺SPARC/Solaris 8運(yùn)行在US locale環(huán)境中,現(xiàn)在我們想讓它運(yùn)行在
IE(Ireland) locale環(huán)境中,以便可以使用歐洲日期格式,怎么辦?
A: Sharad Ramachandran <estancio@hotmail.com>;
運(yùn)行sys-unconfig,在此之前請man -s 1M sys-unconfig,
A: chad schrock <chad@radix.net>;
天啊,為了拍死一只蒼蠅,你要引爆原子彈嗎?
只需要做如下操作,在你的.cshrc/.profile/.bashrc等啟動腳本中設(shè)置$LANG環(huán)境變
量的值為en_UK,注銷,重新登錄即可。為了使這個設(shè)置全局有效,修改
/etc/default/init文件,LANG=en_UK,重啟動。
--------------------------------------------------------------------------
# @(#)init.dfl 1.2 92/11/26
#
# This file is /etc/default/init. /etc/TIMEZONE is a symlink to this file.
# This file looks like a shell script, but it is not. To maintain
# compatibility with old versions of /etc/TIMEZONE, some shell constructs
# (i.e., export commands) are allowed in this file, but are ignored.
#
# Lines of this file should be of the form VAR=value, where VAR is one of
# TZ, LANG, or any of the LC_* environment variables.
#
TZ=GMT+8
LANG=zh.GBK
--------------------------------------------------------------------------
參看locale(1)和locale(5),了解更多關(guān)于locale的信息。運(yùn)行"locale -a",查看
當(dāng)前系統(tǒng)所支持的所有l(wèi)ocale。
A: Sun Microsystems 2001-06-12
有三種方式改變locale。首先用"locale -a"命令確認(rèn)系統(tǒng)中已安裝的locale
1) 從CDE登錄屏幕上修改locale
選擇 options ->; languages ->; choose the new locale
注意,如果登錄用戶的初始化文件中有不同的locale設(shè)置,將優(yōu)先于系統(tǒng)全局locale
設(shè)置。
2) 臨時設(shè)置locale(shell相關(guān)的)
ksh : LANG=<locale>;
sh : LANG=<locale>;
export LANG
csh : setenv LANG <locale>;
bash: export LANG=en_US(zh.GBK)
3) vi /etc/default/init
增加如下內(nèi)容
LANG=<locale>;
LC_ALL=<locale>;
重啟系統(tǒng)。
運(yùn)行"locale"命令確認(rèn)改變生效。
如果你希望使用的locale并未安裝,參看如下文檔安裝locale
Solaris 8 : <<International Language Environments Guide>;>;
Solaris 7 : <<Solaris Internationalization Guide For Developers>;>;
Solaris 2.6: <<Solaris Internationalization Guide for Developers>;>;
D: scz <scz@nsfocus.com>; 1998-08
SPARC/Solaris 2.5下,為了在vi中正確看到中文需要設(shè)置環(huán)境變量
sh
LANG=C;export LANG
LC_CTYPE=iso_8859_1;export LC_CTYPE
csh
setenv LANG zh
關(guān)于設(shè)置LANG這個環(huán)境變量涉及到/usr/lib/locale下的目錄權(quán)限。
1.5 Solaris 7自動注銷
Q: 怎樣設(shè)置才能30秒后自動注銷
A: shridhara
不幸的是,Solaris對此沒有什么好的支持。如果正在使用telnet會話,或許可以考
慮"logout"變量,參看telnet的手冊頁。一個變通的辦法,使用K-Shell,它支持
TMOUT變量,用于指定非活動時限(以秒為單位)。比如,如果一個shell會話3分鐘內(nèi)
不活動,則終止這個shell會話
$ TMOUT=180;export TMOUT
可以在用戶的.profile文件中放置該行。缺點(diǎn)是你只能使用ksh。
D: scz <scz@nsfocus.com>;
vi /etc/default/login
# TIMEOUT sets the number of seconds (between 0 and 900) to wait before
# abandoning a login session.
#
TIMEOUT=180
這里的超時設(shè)置針對登錄過程,而不是登錄成功后的shell會話超時設(shè)置。
1.6 一個目錄擁有setgid設(shè)置,怎么理解
Q: 對一個目錄做了setgid設(shè)置,可我并沒有發(fā)現(xiàn)這和正常情況有什么區(qū)別
A: John Riddoch <jr@scms.rgu.ac.uk>;
在這種目錄下創(chuàng)建新文件時將采用setgid設(shè)置對應(yīng)的屬組,比如
$ ls -ld b
drwxrws--- 2 jr group 512 Mar 14 17:13 b/
$ touch b/a
$ ls -l b/a
-rw------- 1 jr group 0 Mar 14 17:13 b/a
$ id
uid=178(jr) gid=10(staff)
jr的缺省組是staff,而現(xiàn)在b/a文件屬組是group。
D: 小四 <scz@nsfocus.com>;
SPARC/Solaris 7下測試
如果目錄擁有SGID設(shè)置,那么該目錄下新創(chuàng)建的文件將繼承該目錄的屬組,而不是創(chuàng)
建者所對應(yīng)的GID。
[root@ /export/home/scz]>; id
uid=0(root) gid=1(other) <-- 注意當(dāng)前用戶的屬組
[root@ /export/home/scz]>; mkdir groupsgid
[root@ /export/home/scz]>; ls -ld groupsgid
drwxr-xr-x root other groupsgid/
[root@ /export/home/scz]>; chown scz:users groupsgid
[root@ /export/home/scz]>; chmod g+s groupsgid
[root@ /export/home/scz]>; ls -ld groupsgid
drwxr-sr-x scz users groupsgid/ <-- 目錄擁有SGID設(shè)置
[root@ /export/home/scz]>; cd groupsgid/
[root@ /export/home/scz/groupsgid]>; touch scz_0
[root@ /export/home/scz/groupsgid]>; ls -l scz_0
-rw-r--r-- root users scz_0 <-- 注意屬組變化
[root@ /export/home/scz/groupsgid]>; chmod g-s ../groupsgid/
[root@ /export/home/scz/groupsgid]>; ls -ld ../groupsgid/
drwxr-xr-x scz users ../groupsgid/
[root@ /export/home/scz/groupsgid]>; touch scz_1
[root@ /export/home/scz/groupsgid]>; ls -l scz_1
-rw-r--r-- root other scz_1 <-- 注意屬組變化
[root@ /export/home/scz/groupsgid]>;
1.7 非Sun Console上有無等價Stop-A的按鍵
A: neomilev
如果是便攜機(jī),嘗試alt/break 或者 ctrl/break。如果是vt100終端,嘗試F11 或者
break
1.8 如何讓一個用戶只能ftp而無法telnet
A: 小四 <cloudsky@263.net>;
修改該用戶在/etc/passwd中的shell為/bin/false,在/etc/shells文件中增加
/bin/false,此時,該用戶只能ftp,telnet失敗。
1.10 為什么Sun工作站非要輸入boot命令才能啟動
Q: 我有臺Sun工作站,每次開機(jī)后停在ok狀態(tài)下,需要手工輸入boot命令才能啟動,
現(xiàn)在想避免這種效果,怎么辦
A: /usr/sbin/eeprom auto-boot?=true
/usr/sbin/eeprom auto-boot? <-- 查詢
A: dengdai@SMTH
進(jìn)入OBP狀態(tài)
ok setenv auto-boot? true
ok setenv boot-device disk
反之
ok setenv auto-boot? false
1.11 如何讓Solaris識別新增加的硬件
Q: 比如新增加了網(wǎng)卡、硬盤、光驅(qū)什么的,如何讓Solaris意識到這種增加
A: spp(低音炮) & suxm <suxm@gnuchina.org>;
有三種辦法
a. Stop-A進(jìn)入OBP狀態(tài),輸入boot -r
b. sync(重復(fù));reboot -- -r
c. touch /reconfigure;sync(重復(fù));reboot
參看reboot(1M)、boot(1M)、eeprom(1M)、kernel(1M)、cfgadm(1M)、psradm(1M)手
冊頁
Q: 我新增加了一塊硬盤,不想boot -r而立即生效,怎么辦
A: 老大 <willxu@public.cs.hn.cn>; 2001-12-04 16:51
直接將第二塊硬盤接上去,然后順序執(zhí)行如下命令,不用重新啟動機(jī)器
modunload -i 0
drvconfig(1M)
devlinks(1M)
disks(1M)
如果需要重新格式化、分區(qū)、創(chuàng)建文件系統(tǒng),就繼續(xù)執(zhí)行
format(1M)
newfs(1M)
2. 堆棧相關(guān)問題
2.1 如何理解pstack的輸出信息
Q: 080603a7 main (1, 80479b8, 80479c0) + d53
結(jié)尾的d53是什么
A: Roger A. Faulkner <raf@sunraf.Sun.COM>;
在代碼段絕對地址0x080603a7處,main()調(diào)用了一個函數(shù),0x080603a7正是
main + 0xd53,換句話說,從main()函數(shù)開始的0xd53偏移處。
2.3 Solaris中如何獲取一個C程序的調(diào)用;厮
Q: 我想在Solaris 2.6極其后續(xù)版本上獲取一個C程序的調(diào)用棧回溯,類似如下輸出
(10) 0x00045e08 integ + 0x408 [./two_brn.e]
(11) 0x0006468c trajcem + 0x128 [./two_brn.e]
(12) 0x00055490 fly_traj + 0xf58 [./two_brn.e]
(13) 0x0004052c top_level + 0x14 [./two_brn.e]
(14) 0x000567e4 _start + 0x34 [./two_brn.e]
這樣我就可以知道當(dāng)程序崩潰、死鎖的時候代碼執(zhí)行到了何處。在HP-UX和IRIX上
可以利用U_STACK_TRACE()和trace_back_stack_and_print(),Solaris上呢?
Q: 有沒有辦法顯示當(dāng)前堆棧中的數(shù)據(jù)(GNU/Linux系統(tǒng))?我希望自己的異常處理程序
在進(jìn)程結(jié)束前dump整個棧區(qū)(stack),以便觀察到棧頂是什么函數(shù)。對于調(diào)試意想
不到的運(yùn)行時錯誤而言,這很重要。
A: Bjorn Reese <breese@mail1.stofanet.dk>;
用/usr/proc/bin/pstack [-F] <pid ...>;
參看這個例子代碼,http://home1.stofanet.dk/breese/debug/debug.tar.gz
Q: is there a way to access call stack information at run time from within
a program? i've been maintaining my own crude stack using __FUNCTION__
and linked lists but can't help but think there's gotta be a better
way...
A: Nate Eldredge <neldredge@hmc.edu>;
這依賴于你的系統(tǒng),如果使用glibc 2.1或更新版本,可以使用backtrace()函數(shù),
參看<execinfo.h>;,其他系統(tǒng)可能有不同的技術(shù)支持。
注意,你所使用的辦法可能是唯一能夠保證跨平臺使用的
A: Andrew Gabriel <andrew@cucumber.demon.co.uk>; Consultant Software Engineer
下面是一個backtrace()的應(yīng)用舉例,如果你使用Solaris 2.4及其后續(xù)版本,那
么這個例子可以很好的工作。很可能無法工作在64-bit模式下,我沒有嘗試過,
好像Solaris 7已經(jīng)提供了一個類似的演示程序。還可以增加某些功能,我沒有時
間了。
/*
* Produce a stack trace for Solaris systems.
*
* Copyright (C) 1995-1998 Andrew Gabriel <andrew@cucumber.demon.co.uk>;
* Parts derived from Usenet postings of Bart Smaalders and Casper Dik.
*
*/
/* ......................................................................... */
#include <setjmp.h>;
#include <sys/types.h>;
#include <sys/reg.h>;
#include <sys/frame.h>;
#include <dlfcn.h>;
#include <errno.h>;
#include <unistd.h>;
#include <stdio.h>;
#if defined(sparc) || defined(__sparc)
#define FLUSHWIN() asm("ta 3" ;
#define FRAME_PTR_INDEX 1
#define SKIP_FRAMES 0
#endif
#if defined(i386) || defined(__i386)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 3
#define SKIP_FRAMES 1
#endif
#if defined(ppc) || defined(__ppc)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 0
#define SKIP_FRAMES 2
#endif
/* ......................................................................... */
static void print_address ( void * pc )
{
Dl_info info;
if ( dladdr( pc, &info ) == 0 )
{
/* not found */
fprintf( stderr, "*** %s:0x%x\n", "??", ( unsigned int )pc );
}
else
{
/* found */
fprintf( stderr, "*** %s:%s+0x%x\n", info.dli_fname, info.dli_sname,
( unsigned int )pc - ( unsigned int )info.dli_saddr );
}
return;
} /* end of print_address */
/* ......................................................................... */
static int validaddr ( void * addr )
{
static long pagemask = -1;
char c;
if ( pagemask == -1 )
{
pagemask = ~( sysconf( _SC_PAGESIZE ) - 1 );
}
addr = ( void * )( ( long )addr & pagemask );
if ( mincore( ( char * )addr, 1, &c ) == -1 && errno == ENOMEM )
{
return 0; /* invalid */
}
else
{
return 1; /* valid */
}
} /* end of validaddr */
/* ......................................................................... */
/*
* this function walks up call stack, calling print_addess
* once for each stack frame, passing the pc as the argument.
*/
static void print_stack ( void )
{
struct frame * sp;
jmp_buf env;
int i;
int * iptr;
FLUSHWIN();
setjmp( env );
iptr = ( int * )env;
sp = ( struct frame * )iptr[ FRAME_PTR_INDEX ];
for ( i = 0; i < SKIP_FRAMES && sp; i++ )
{
if ( !validaddr( sp ) || !validaddr( &sp->;fr_savpc ) )
{
fprintf( stderr, "***[stack pointer corrupt]\n" );
return;
}
sp = ( struct frame * )sp->;fr_savfp;
}
i = 100; /* looping check */
while ( validaddr( sp ) && validaddr( &sp->;fr_savpc ) && sp->;fr_savpc && --i
)
{
print_address( ( void * )sp->;fr_savpc );
sp = ( struct frame * )sp->;fr_savfp;
}
} /* end of print_stack */
/* ......................................................................... */
void backtrace( void )
{
fprintf( stderr, "***backtrace...\n" );
print_stack();
fprintf( stderr, "***backtrace ends\n" );
}
/* ......................................................................... */
2.4 如何編程獲取棧底地址
Q: 雖然很多操作系統(tǒng)的用戶進(jìn)程棧底地址固定,但是我需要寫一個可廣泛移植C程序
獲取這個棧底地址。
A: tt <warning3@nsfocus.com>; 2001-06-02 19:40
假設(shè)堆棧(stack)向低地址方向增長,則所謂棧底指堆棧(stack)最高地址
x86/Linux 棧底是0xc0000000( 棧底往低地址的4個字節(jié)總是零 )
SPARC/Solaris 7/8 棧底是0xffbf0000( 棧底往低地址的4個字節(jié)總是零 )
SPARC/Solaris 2.6 棧底是0xf0000000( 棧底往低地址的4個字節(jié)總是零 )
x86/FreeBSD 棧底是0xbfc00000( 棧底往低地址的4個字節(jié)總是零 )
x86/NetBSD 1.5 棧底是0xbfbfe000
x86/OpenBSD 2.8 棧底是0xdfbfe000
D: jonah
對于NetBSD 1.5,棧底是0xbfc00000。根據(jù)源碼,最高用戶地址是0xbfbfe000,因?yàn)?
最后4MB(2^22)的最后兩頁(0x2000字節(jié),一頁4096字節(jié))保留用做U區(qū),但是目前不再
使用這塊內(nèi)存。因此,0xbfbfe000才是真正的棧底。
tt在OpenBSD 2.8上測試結(jié)果,棧底是0xdfbfe000,注意和NetBSD 1.5相差很大。
A: tt <warning3@nsfocus.com>;
--------------------------------------------------------------------------
/*
* gcc -Wall -O3 -o gstack gstack.c
*
* A simple example to get the current stack bottom address
* warning3 <warning3@nsfocus.com>;
* 2001-06-01
*
* Modified by scz <scz@nsfocus.com>;
* 2001-06-02
*/
#include <stdio.h>;
#include <stdlib.h>;
#include <signal.h>;
#include <unistd.h>;
#include <setjmp.h>;
typedef void Sigfunc ( int ); /* for signal handlers */
Sigfunc * signal ( int signo, Sigfunc * func );
static Sigfunc * Signal ( int signo, Sigfunc * func );
static char * get_stack_bottom ( void );
static void segfault ( int signo );
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump = 0;
static Sigfunc *seg_handler;
static Sigfunc *bus_handler; /* for xxxBSD */
Sigfunc * signal ( int signo, Sigfunc * func )
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset( &act.sa_mask );
act.sa_flags = 0;
if ( sigaction( signo, &act, &oact ) < 0 )
{
return( SIG_ERR );
}
return( oact.sa_handler );
} /* end of signal */
static Sigfunc * Signal ( int signo, Sigfunc * func ) /* for our signal() funct
ion */
{
Sigfunc * sigfunc;
if ( ( sigfunc = signal( signo, func ) ) == SIG_ERR )
{
exit( EXIT_FAILURE );
}
return( sigfunc );
} /* end of Signal */
static char * get_stack_bottom ( void )
{
volatile char *c; /* for autovar, must be volatile */
seg_handler = Signal( SIGSEGV, segfault );
bus_handler = Signal( SIGBUS, segfault );
c = ( char * )&c;
if ( sigsetjmp( jmpbuf, 1 ) != 0 )
{
Signal( SIGSEGV, seg_handler );
Signal( SIGBUS, bus_handler );
return( ( char * )c );
}
canjump = 1; /* now sigsetjump() is OK */
while ( 1 )
{
*c = *c;
c++;
}
return( NULL );
} /* end of get_stack_bottom */
static void segfault ( int signo )
{
if ( canjump == 0 )
{
return; /* unexpected signal, ignore */
}
canjump = 0;
siglongjmp( jmpbuf, signo ); /* jump back to main, don't return */
} /* end of segfault */
int main ( int argc, char * argv[] )
{
fprintf( stderr, "Current stack bottom is at 0x%p\n", get_stack_bottom() );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
D: scz <scz@nsfocus.com>; 2001-06-03 00:38
W. Richard Stevens在<<Advanced Programming in the UNIX Environment>;>;中詳細(xì)
介紹了setjmp/longjmp以及sigsetjmp/siglongjmp函數(shù)。
這個程序的原理很簡單,不斷向棧底方向取值,越過棧底的地址訪問會導(dǎo)致SIGSEGV
信號,然后利用長跳轉(zhuǎn)回到主流程報告當(dāng)前c值,自然對應(yīng)棧底。
tt測試表明,在x86/FreeBSD中導(dǎo)致SIGBUS信號。據(jù)jonah報告,不僅僅是FreeBSD,
NetBSD 以及 OpenBSD 系統(tǒng)中上述程序越界訪問也導(dǎo)致SIGBUS信號,而不是SIGSEGV
信號。
非局部轉(zhuǎn)移,比如函數(shù)間轉(zhuǎn)移的時候考慮使用setjmp/longjmp。但是如果涉及到信號
句柄與主流程之間的轉(zhuǎn)移,就不能使用longjmp了。當(dāng)捕捉到信號進(jìn)入信號句柄,此
時當(dāng)前信號被自動加入進(jìn)程的信號屏蔽字中,阻止后來產(chǎn)生的這種信號干擾此信號句
柄。如果用longjmp跳出信號句柄,此時進(jìn)程的信號屏蔽字狀態(tài)未知,有些系統(tǒng)做了
保存恢復(fù),有些系統(tǒng)沒有做。根據(jù)POSIX.1,此時應(yīng)該使用sigsetjmp/siglongjmp函
數(shù)。下面來自SPARC/Solaris 7的setjmp(3C)
--------------------------------------------------------------------------
#include <setjmp.h>;
int setjmp ( jmp_buf env );
int sigsetjmp ( sigjmp_buf env, int savemask );
void longjmp ( jmp_buf env, int val );
void siglongjmp ( sigjmp_buf env, int val );
--------------------------------------------------------------------------
如果savemask非0,sigsetjmp在env中保存進(jìn)程當(dāng)前信號屏蔽字,相應(yīng)siglongjmp回
來的時候從env中恢復(fù)信號屏蔽字。
數(shù)據(jù)類型sig_atomic_t由ANSI C定義,在寫時不會被中斷。它意味著這種變量在具有
虛存的系統(tǒng)上不會跨越頁邊界,可以用一條機(jī)器指令對其存取。這種類型的變量總是
與ANSI類型修飾符volatile一并出現(xiàn),防止編譯器優(yōu)化帶來的不確定狀態(tài)。
在longjmp/siglongjmp中,全局、靜態(tài)變量保持不變,聲明為volatile的自動變量也
保持不變。
無論是否使用了編譯優(yōu)化開關(guān),為了保證廣泛兼容性,都應(yīng)該在get_stack_bottom()
中聲明c為volatile變量。
注意這里,必須使用長跳轉(zhuǎn),而不能從信號句柄中直接返回。因?yàn)閷?dǎo)致信號SIGSEGV、
SIGBUS分發(fā)的語句始終存在,直接從信號句柄中返回主流程,將回到引發(fā)信號的原指
令處,而不是下一條指令(把這種情況理解成異常,而不是中斷),于是立即導(dǎo)致下一
次信號分發(fā),出現(xiàn)廣義上的死循環(huán),所謂程序僵住?梢院唵涡薷纳鲜龀绦颍焕
長跳轉(zhuǎn),簡單對一個全局變量做判斷決定是否繼續(xù)循環(huán)遞增c,程序最終僵住;如果
在信號句柄中輸出調(diào)試信息,很容易發(fā)現(xiàn)這個廣義上的無限循環(huán)。
D: scz <scz@nsfocus.com>; 2001-06-03 00:40
在x86/Linux系統(tǒng)中用如下命令可以確定棧區(qū)所在
# cat /proc/1/maps <-- 觀察1號進(jìn)程init
... ...
bfffe000-c0000000 rwxp fffff000 00:00 0
#
在SPARC/Solaris 7中用/usr/proc/bin/pmap命令確定棧區(qū)所在
# /usr/proc/bin/pmap 1 <-- 觀察1號進(jìn)程init
... ...
FFBEC000 16K read/write/exec [ stack ]
#
16KB == 0x4000,0xFFBEC000 + 0x4000 == 0xFFBF0000
與前面tt介紹的
SPARC/Solaris 7/8 棧底是0xffbf0000( 棧底往低地址的4個字節(jié)總是零 )
相符合。
此外,在SPARC/Solaris 7下,可以這樣驗(yàn)證之
# /usr/ccs/bin/nm -nx /dev/ksyms | grep "|_userlimit"
[7015] |0x0000100546f8|0x000000000008|OBJT |GLOB |0 |ABS |_userlimit
[8051] |0x000010054700|0x000000000008|OBJT |GLOB |0 |ABS |_userlimit32
# echo "_userlimit /J" | adb -k /dev/ksyms /dev/mem
physmem 3b72
_userlimit:
_userlimit: ffffffff80000000
# skd64 0x000010054700 8
byteArray [ 8 bytes ] ---->;
0000000000000000 00 00 00 00 FF BF 00 00
# ~~~~~~~~~~~ 對于32-bit應(yīng)用程序來說,這是用戶
空間上限
如果編譯64-bit應(yīng)用程序,用戶空間上限是_userlimit,也就是0xffffffff80000000
# /opt/SUNWspro/SC5.0/bin/cc -xarch=v9 -O -o gstack gstack.c
# ./gstack
Current stack bottom is at 0xffffffff80000000
#
對于SPARC/Solaris 2.6 32-bit kernel mode
# echo "_userlimit /X" | adb -k /dev/ksyms /dev/mem
physmem 3d24
_userlimit:
_userlimit: f0000000
#
2.5 如何得到一個運(yùn)行中進(jìn)程的內(nèi)存映像
A: Sun Microsystems 1998-03-30
有些時候必須得到一個運(yùn)行中進(jìn)程的內(nèi)存映像而不能停止該進(jìn)程,Solaris系統(tǒng)了這
樣的工具,gcore為運(yùn)行中進(jìn)程創(chuàng)建一個core文件。假設(shè)我的bash進(jìn)程號是5347
# gcore 5347
gcore: core.5347 dumped
# file core.5347
core.5347: ELF 32-位 MSB core文件 SPARC 版本 1,來自'bash'
#
注意,只能獲取屬主是你自己的進(jìn)程的內(nèi)存映像,除非你是root。
2.6 調(diào)試器如何工作的
Q: 我想在一個自己編寫的程序中單步運(yùn)行另外一個程序,換句話說,那是一個調(diào)試
器,該如何做?
A: Erik de Castro Lopo <nospam@mega-nerd.com>;
這是一個操作系統(tǒng)相關(guān)的問題。最一般的回答是使用ptrace()系統(tǒng)調(diào)用,盡管我
不確認(rèn)究竟這有多么普遍。Linux man手冊上說SVr4、SVID EXT、AT&T、X/OPEN
和BSD 4.3都支持它。
為了使用ptrace(),你的程序應(yīng)該調(diào)用fork(),然后在子進(jìn)程中做如下調(diào)用:
ptrace( PTRACE_TRACEME, 0, 0, 0 );
接下來調(diào)用exec()家族的函數(shù)執(zhí)行你最終企圖跟蹤的程序。
為了單步進(jìn)入子進(jìn)程,在父進(jìn)程中調(diào)用:
ptrace( PTRACE_SINGLESTEP, 0, 0, 0 );
還有一些其他函數(shù)做恢復(fù)/設(shè)置寄存器、內(nèi)存變量一類的工作。
GDB的源代碼足以回答這個問題。
2.7 x86/Linux上如何處理SIGFPE信號
Q: 參看如下程序
--------------------------------------------------------------------------
/*
* gcc -Wall -pipe -O3 -o sigfpe_test_0 sigfpe_test_0.c
*
* 注意與下面的編譯效果進(jìn)行對比,去掉優(yōu)化開關(guān)-O3
*
* gcc -Wall -pipe -o sigfpe_test_0 sigfpe_test_0.c
*/
#include <stdio.h>;
#include <stdlib.h>;
#include <string.h>;
#include <signal.h>;
#include <unistd.h>;
#include <setjmp.h>;
/*
* for signal handlers
*/
typedef void Sigfunc ( int );
Sigfunc * signal ( int signo, Sigfunc *func );
static Sigfunc * Signal ( int signo, Sigfunc *func );
static void on_fpe ( int signo );
Sigfunc * signal ( int signo, Sigfunc *func )
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset( &act.sa_mask );
act.sa_flags = 0;
if ( signo == SIGALRM )
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
}
else
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if ( sigaction( signo, &act, &oact ) < 0 )
{
return( SIG_ERR );
}
return( oact.sa_handler );
} /* end of signal */
static Sigfunc * Signal ( int signo, Sigfunc *func )
{
Sigfunc *sigfunc;
if ( ( sigfunc = signal( signo, func ) ) == SIG_ERR )
{
perror( "signal" );
exit( EXIT_FAILURE );
}
return( sigfunc );
} /* end of Signal */
static void on_fpe ( int signo )
{
fprintf( stderr, "here is on_fpe\n" );
return;
} /* end of on_fpe */
int main ( int argc, char * argv[] )
{
unsigned int i;
Signal( SIGFPE, on_fpe );
i = 51211314 / 0;
/*
* 另外,增加這行后,再次對比有-O3和無-O3的效果
*
* fprintf( stderr, "i = %#X\n", i );
*/
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
有-O3、無-O3,以及有無最后那條fprintf()語句,效果上有差別,自行對比。如果
輸出"here is on_fpe",則會發(fā)現(xiàn)永不停止。
D: 小四 <scz@nsfocus.com>; 2001-12-14 18:25
為了便于討論,約定兩個名詞,中斷和異常。這里中斷指最常規(guī)的中斷,比如int指
令帶來的軟中斷。異常的典型代表有除0錯。區(qū)別在于,發(fā)生異常時,x86架構(gòu)上CPU
將當(dāng)前EIP(指向引發(fā)異常的指令)壓棧,發(fā)生中斷時,x86架構(gòu)上CPU將當(dāng)前EIP的后一
個地址(指向引發(fā)中斷的指令的后一條指令)壓棧。在異常處理代碼中,如果認(rèn)為能夠
從災(zāi)難中恢復(fù),可以不修改被壓棧的EIP,從而返回到引發(fā)異常的指令處。更多細(xì)節(jié)
請查看Intel手冊。
這些是從前DOS下殘留的匯編知識,不過也快忘光了,剛才又找元寶寶確認(rèn)了一下。
在上述代碼中,on_fpe()直接返回了,導(dǎo)致再次觸發(fā)異常,所以無休止輸出。事實(shí)上
在所有的計(jì)算器處理程序中,都會對SIGFPE信號做相應(yīng)處理,前些日子看yacc/lex的
時候又碰上過。正確的做法是,利用遠(yuǎn)跳轉(zhuǎn)轉(zhuǎn)移,讓開引發(fā)異常的指令。
代碼修改如下
--------------------------------------------------------------------------
/*
* gcc -Wall -pipe -O3 -o sigfpe_test_1 sigfpe_test_1.c
*
* 注意與下面的編譯效果進(jìn)行對比,去掉優(yōu)化開關(guān)-O3
*
* gcc -Wall -pipe -o sigfpe_test_1 sigfpe_test_1.c
*/
#include <stdio.h>;
#include <stdlib.h>;
#include <string.h>;
#include <signal.h>;
#include <unistd.h>;
#include <setjmp.h>;
/*
* for signal handlers
*/
typedef void Sigfunc ( int );
Sigfunc * signal ( int signo, Sigfunc *func );
static Sigfunc * Signal ( int signo, Sigfunc *func );
static void on_fpe ( int signo );
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump = 0;
Sigfunc * signal ( int signo, Sigfunc *func )
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset( &act.sa_mask );
act.sa_flags = 0;
if ( signo == SIGALRM )
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
}
else
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if ( sigaction( signo, &act, &oact ) < 0 )
{
return( SIG_ERR );
}
return( oact.sa_handler );
} /* end of signal */
static Sigfunc * Signal ( int signo, Sigfunc *func )
{
Sigfunc *sigfunc;
if ( ( sigfunc = signal( signo, func ) ) == SIG_ERR )
{
perror( "signal" );
exit( EXIT_FAILURE );
}
return( sigfunc );
} /* end of Signal */
static void on_fpe ( int signo )
{
if ( canjump == 0 )
{
return; /* unexpected signal, ignore */
}
canjump = 0;
fprintf( stderr, "here is on_fpe\n" );
siglongjmp( jmpbuf, signo ); /* jump back to main, don't return */
return;
} /* end of on_fpe */
int main ( int argc, char * argv[] )
{
unsigned int i;
if ( sigsetjmp( jmpbuf, 1 ) != 0 )
{
fprintf( stderr, "c u later\n" );
return( EXIT_SUCCESS );
}
/*
* now sigsetjump() is OK
*/
canjump = 1;
Signal( SIGFPE, on_fpe );
i = 51211314 / 0;
/*
* 另外,增加這行后,再次對比有-O3和無-O3的效果
*
* fprintf( stderr, "i = %#X\n", i );
*/
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
關(guān)于-O3的討論,對gcc編譯器熟悉的朋友請繼續(xù),呵,我對Linux下的這此東西,實(shí)
在缺乏興趣。
3. -lelf、-lkvm、-lkstat相關(guān)問題
3.1 如何判斷可執(zhí)行文件是否攜帶了調(diào)試信息
Q: 某些時候需要知道編譯可執(zhí)行文件時是否攜帶了調(diào)試信息(比如是否指定了-g編譯
選項(xiàng))。檢查可執(zhí)行文件中是否包含".stab" elf section,".stab" section用于
保存相關(guān)調(diào)試信息。
A: Sun Microsystems 2000-05-15
下面這個腳本演示如何判斷可執(zhí)行文件是否攜帶調(diào)試信息
--------------------------------------------------------------------------
#! /bin/sh
#
# Script that test whether or not a given file has been built for
# debug (-g option specified in the compilation)
if [ $# -le 0 ]
then
echo "Usage: $1 filename"
exit 1
fi
if [ ! -f $1 ]
then
echo "File $1 does not exist"
exit 1
fi
/usr/ccs/bin/dump -hv $1 | /bin/egrep -s '.stab$'
if [ $? -eq 0 ]
then
echo "File '$1' has been built for debug"
exit 0
else
echo "File '$1' has not been built for debug"
exit 1
fi
--------------------------------------------------------------------------
如果對ELF文件格式不熟悉,理解上述代碼可能有點(diǎn)困難,參看
http://www.digibel.org/~tompy/hacking/elf.txt,這是1.1版的ELF文件格式規(guī)范。
3.2 mprotect如何用
A: 小四 <cloudsky@263.net>;
# truss prtconf 2>;&1 | grep sysconf
sysconfig(_CONFIG_PAGESIZE) = 8192
sysconfig(_CONFIG_PHYS_PAGES) = 16384
#
由此可知當(dāng)前系統(tǒng)頁尺寸是8192字節(jié)。
--------------------------------------------------------------------------
/*
* gcc -Wall -g -ggdb -static -o mtest mtest.c
*/
#include <stdio.h>;
#include <stdlib.h>;
#include <errno.h>;
#include <sys/mman.h>;
int main ( int argc, char * argv[] )
{
char *buf;
char c;
/*
* 分配一塊內(nèi)存,擁有缺省的rw-保護(hù)
*/
buf = ( char * )malloc( 1024 + 8191 );
if ( !buf )
{
perror( "malloc" );
exit( errno );
}
/*
* Align to a multiple of PAGESIZE, assumed to be a power of two
*/
buf = ( char * )( ( ( unsigned int )buf + 8191 ) & ~8191 );
c = buf[77];
buf[77] = c;
printf( "ok\n" );
/*
* Mark the buffer read-only.
*
* 必須保證這里buf位于頁邊界上,否則mprotect()失敗,報告無效參數(shù)
*/
if ( mprotect( buf, 1024, PROT_READ ) )
{
perror( "\nmprotect" );
exit( errno );
}
c = buf[77];
/*
* Write error, program dies on SIGSEGV
*/
buf[77] = c;
exit( 0 );
} /* end of main */
--------------------------------------------------------------------------
$ ./mtest
ok
段錯誤 (core dumped) <-- 內(nèi)存保護(hù)起作用了
$
3.3 mmap如何用
A: 小四 <cloudsky@263.net>;
下面寫一個完成文件復(fù)制功能的小程序,利用mmap(2),而不是標(biāo)準(zhǔn)文件I/O接口。
--------------------------------------------------------------------------
/*
* gcc -Wall -O3 -o copy_mmap copy_mmap.c
*/
#include <stdio.h>;
#include <stdlib.h>;
#include <string.h>; /* for memcpy */
#include <strings.h>;
#include <sys/mman.h>;
#include <sys/types.h>;
#include <sys/stat.h>;
#include <fcntl.h>;
#include <unistd.h>;
#define PERMS 0600
int main ( int argc, char * argv[] )
{
int src, dst;
void *sm, *dm;
struct stat statbuf;
if ( argc != 3 )
{
fprintf( stderr, " Usage: %s <source>; <target>;\n", argv[0] );
exit( EXIT_FAILURE );
}
if ( ( src = open( argv[1], O_RDONLY ) ) < 0 )
{
perror( "open source" );
exit( EXIT_FAILURE );
}
/* 為了完成復(fù)制,必須包含讀打開,否則mmap()失敗 */
if ( ( dst = open( argv[2], O_RDWR | O_CREAT | O_TRUNC, PERMS ) ) < 0 )
{
perror( "open target" );
exit( EXIT_FAILURE );
}
if ( fstat( src, &statbuf ) < 0 )
{
perror( "fstat source" );
exit( EXIT_FAILURE );
}
/*
* 參看前面man手冊中的說明,mmap()不能用于擴(kuò)展文件長度。所以這里必須事
* 先擴(kuò)大目標(biāo)文件長度,準(zhǔn)備一個空架子等待復(fù)制。
*/
if ( lseek( dst, statbuf.st_size - 1, SEEK_SET ) < 0 )
{
perror( "lseek target" );
exit( EXIT_FAILURE );
}
if ( write( dst, &statbuf, 1 ) != 1 )
{
perror( "write target" );
exit( EXIT_FAILURE );
}
/* 讀的時候指定 MAP_PRIVATE 即可 */
sm = mmap( 0, ( size_t )statbuf.st_size, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, src, 0 );
if ( MAP_FAILED == sm )
{
perror( "mmap source" );
exit( EXIT_FAILURE );
}
/* 這里必須指定 MAP_SHARED 才可能真正改變靜態(tài)文件 */
dm = mmap( 0, ( size_t )statbuf.st_size, PROT_WRITE,
MAP_SHARED, dst, 0 );
if ( MAP_FAILED == dm )
{
perror( "mmap target" );
exit( EXIT_FAILURE );
}
memcpy( dm, sm, ( size_t )statbuf.st_size );
/*
* 可以不要這行代碼
*
* msync( dm, ( size_t )statbuf.st_size, MS_SYNC );
*/
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
mmap()好處是處理大文件時速度明顯快于標(biāo)準(zhǔn)文件I/O,無論讀寫,都少了一次用戶
空間與內(nèi)核空間之間的復(fù)制過程。操作內(nèi)存還便于設(shè)計(jì)、優(yōu)化算法。
文件I/O操作/proc/self/mem不存在頁邊界對齊的問題。至少Linux的mmap()的最后一
個形參offset并未強(qiáng)制要求頁邊界對齊,如果提供的值未對齊,系統(tǒng)自動向上舍入到
頁邊界上。
malloc()分配得到的地址不見得對齊在頁邊界上
/proc/self/mem和/dev/kmem不同。root用戶打開/dev/kmem就可以在用戶空間訪問到
內(nèi)核空間的數(shù)據(jù),包括偏移0處的數(shù)據(jù),系統(tǒng)提供了這樣的支持。
顯然代碼段經(jīng)過/proc/self/mem可寫映射后已經(jīng)可寫,無須mprotect()介入。
D: scz <scz@nsfocus.com>;
Solaris 2.6下參看getpagesize(3C)手冊頁,關(guān)于如何獲取頁大小,一般是8192。
Linux下參看getpagesize(2)手冊頁,一般是4096。
3.4 getrusage如何用
A: 小四 <cloudsky@263.net>;
在SPARC/Solaris 2.6/7下結(jié)論一致,只支持了ru_utime和ru_stime成員,其他成員
被設(shè)置成0。修改頭文件后在FreeBSD 4.3-RELEASE上測試,則不只支持ru_utime和
ru_stime成員。從FreeBSD的getrusage(2)手冊頁可以看到,這個函數(shù)源自4.2 BSD。
如此來說,至少對于SPARC/Solaris 2.6/7,getrusage(3C)并無多大意義。
3.5 setitimer如何用
D: scz <scz@nsfocus.com>;
為什么要學(xué)習(xí)使用setitimer(2),因?yàn)閍larm(3)屬于被淘汰的定時器技術(shù)。
A: 小四 <cloudsky@263.net>;
下面是個x86/FreeBSD 4.3-RELEASE下的例子
--------------------------------------------------------------------------
/*
* File : timer_sample.c
* Author : Unknown (Don't ask me anything about this program)
* Complie : gcc -Wall -pipe -O3 -o timer_sample timer_sample.c
* Platform : x86/FreeBSD 4.3-RELEASE
* Date : 2001-09-18 15:18
*/
/************************************************************************
* *
* Head File *
* *
************************************************************************/
#include <stdio.h>;
#include <stdlib.h>;
#include <sys/time.h>;
#include <signal.h>;
/************************************************************************
* *
* Macro *
* *
************************************************************************/
typedef void Sigfunc ( int ); /* for signal handlers */
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
static void Atexit ( void ( *func ) ( void ) );
static void init_signal ( void );
static void init_timer ( void );
static void on_alarm ( int signo );
static void on_terminate ( int signo );
static int Setitimer ( int which, const struct itimerval *value,
struct itimerval *ovalue );
Sigfunc * signal ( int signo, Sigfunc *func );
static Sigfunc * Signal ( int signo, Sigfunc *func );
static void terminate ( void );
/************************************************************************
* *
* Static Global Var *
* *
************************************************************************/
/************************************************************************/
static void Atexit ( void ( *func ) ( void ) )
{
if ( atexit( func ) != 0 )
{
perror( "atexit" );
exit( EXIT_FAILURE );
}
return;
} /* end of Atexit */
/*
* 初始化信號句柄
*/
static void init_signal ( void )
{
int i;
Atexit( terminate );
for ( i = 1; i < 9; i++ )
{
Signal( i, on_terminate );
}
Signal( SIGTERM, on_terminate );
Signal( SIGALRM, on_alarm );
return;
} /* end of init_signal */
static void init_timer ( void )
{
struct itimerval value;
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval = value.it_value;
Setitimer( ITIMER_REAL, &value, NULL );
} /* end of init_timer */
static void on_alarm ( int signo )
{
static int count = 0;
/*
* 演示用,這很危險
*/
fprintf( stderr, "count = %u\n", count++ );
return;
}
static void on_terminate ( int signo )
{
/*
* 這次我們使用atexit()函數(shù)
*/
exit( EXIT_SUCCESS );
} /* end of on_terminate */
static int Setitimer ( int which, const struct itimerval *value,
struct itimerval *ovalue )
{
int ret;
if ( ( ret = setitimer( which, value, ovalue ) ) < 0 )
{
perror( "setitimer" );
exit( EXIT_FAILURE );
}
return( ret );
} /* end of Setitimer */
Sigfunc * signal ( int signo, Sigfunc *func )
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset( &act.sa_mask );
act.sa_flags = 0;
if ( signo == SIGALRM )
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
}
else
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if ( sigaction( signo, &act, &oact ) < 0 )
{
return( SIG_ERR );
}
return( oact.sa_handler );
} /* end of signal */
static Sigfunc * Signal ( int signo, Sigfunc *func )
{
Sigfunc *sigfunc;
if ( ( sigfunc = signal( signo, func ) ) == SIG_ERR )
{
perror( "signal" );
exit( EXIT_FAILURE );
}
return( sigfunc );
} /* end of Signal */
static void terminate ( void )
{
fprintf( stderr, "\n" );
return;
} /* end of terminate */
int main ( int arg, char * argv[] )
{
init_signal();
init_timer();
while ( 1 )
{
/*
* 形成阻塞,降低CPU占用率
*/
getchar();
}
return( EXIT_SUCCESS );
} /* end of main */
/************************************************************************/
--------------------------------------------------------------------------
D: scz <scz@nsfocus.com>;
討論一個問題。getchar()的作用是降低CPU占用率,可用top命令查看。
timer_sample.c中換用ITIMER_PROF/SIGPROF后,你會發(fā)現(xiàn)上述程序無輸出,我據(jù)此
認(rèn)為getchar()形成的阻塞不計(jì)算在進(jìn)程虛擬時鐘中,也不認(rèn)為系統(tǒng)正在為進(jìn)程利益
而運(yùn)行。
如果進(jìn)一步將getchar()去掉,直接一個while()無限循環(huán),即使換用
ITIMER_PROF/SIGPROF,程序還是有輸出。不過top命令查看的結(jié)果讓你吐血,CPU幾
乎無空閑。
D: scz <scz@nsfocus.com>;
setitimer( ITIMER_REAL, &value, NULL )導(dǎo)致分發(fā)SIGALRM信號,如果同時使用
alarm(),勢畢造成沖突。此外注意sleep()、pause()等函數(shù)帶來的沖突。
4. 系統(tǒng)資源相關(guān)問題
4.1 主流Unix操作系統(tǒng)上如何編程獲取進(jìn)程的內(nèi)存、CPU利用狀況
Q: Solaris下如何編程獲知CPU占用率和內(nèi)存占用信息呢,可移植嗎?
Q: 我想寫個程序遍歷當(dāng)前運(yùn)行中的活動進(jìn)程,Solaris提供相應(yīng)系統(tǒng)調(diào)用了嗎
A: Nicholas Dronen <ndronen@io.frii.com>;
不可移植。man -s 4 proc,man -s 3k kstat
如果不是編程,可以用top、mpstat、vmstat、sar(1)等等,還有
/usr/ucb/ps -aux,對于Solaris來說,后者更直接精煉,top不是標(biāo)準(zhǔn)配置。
# /usr/bin/prstat (Solaris 8 prstat(1M)手冊頁)
# /usr/ucb/ps -aux | head (Solaris 2.x)
Q: 主流Unix操作系統(tǒng)上如何編程獲取進(jìn)程的內(nèi)存、CPU利用狀況,AIX、HP、SUN
process memory usage
process cpu time usage
A: Nate Eldredge <neldredge@hmc.edu>;
man -s 3C getrusage
D: 小四 <cloudsky@263.net>;
在SPARC/Solaris 2.6/7下結(jié)論一致,只支持了ru_utime和ru_stime成員,其他成員
被設(shè)置成0。FreeBSD 4.3-RELEASE上測試,則不只支持ru_utime和ru_stime成員。從
FreeBSD的getrusage(2)手冊頁可以看到,這個函數(shù)源自4.2 BSD。
至少對于SPARC/Solaris 2.6/7,getrusage(3C)并無多大意義。
A: Robert Owen Thomas <robt@cymru.com>;
對于Solaris,可以利用procfs接口,下面的例子獲取指定進(jìn)程的內(nèi)存占用情況
--------------------------------------------------------------------------
/*
* @(#)memlook.c 1.0 10 Nov 1997
* Robert Owen Thomas robt@cymru.com
* memlook.c -- A process memory utilization reporting tool.
*
* gcc -Wall -O3 -o memlook memlook.c
*/
#pragma ident "@(#)memlook.c 1.0 10 Nov 1997 Robert Owen Thomas robt@cymru.com"
#include <stdio.h>;
#include <stdlib.h>;
#include <sys/types.h>;
#include <sys/stat.h>;
#include <sys/signal.h>;
#include <sys/syscall.h>;
#include <sys/procfs.h>;
#include <sys/param.h>;
#include <unistd.h>;
#include <fcntl.h>;
int counter = 10;
int showUsage ( const char * );
void getInfo ( int, int );
int main ( int argc, char * argv[] )
{
int fd, pid, timeloop = 0;
char pidpath[BUFSIZ]; /* /usr/include/stdio.h: #define BUFSIZ 1024 */
switch ( argc )
{
case 2:
break;
case 3:
timeloop = atoi( argv[2] );
break;
default:
showUsage( argv[0] );
break;
} /* end of switch */
pid = atoi( argv[1] );
sprintf( pidpath, "/proc/%-d", pid ); /* -表示向左靠 */
/*
* /proc/1/是目錄,但在這種用法中,就是直接打開目錄,不是打開文件
*/
if ( ( fd = open( pidpath, O_RDONLY ) ) < 0 )
{
perror( pidpath );
exit( 1 );
}
if ( 0 < timeloop )
{
for ( ; ; )
{
getInfo( fd, pid );
sleep( timeloop );
}
}
getInfo( fd, pid );
close( fd );
exit( 0 );
} /* end of main */
int showUsage ( const char * progname )
{
fprintf( stderr, "%s: usage: %s < PID >; [time delay]\n", progname, progname
);
exit( 3 );
} /* end of showUsage */
void getInfo ( int fd, int pid )
{
prpsinfo_t prp;
prstatus_t prs;
if ( ioctl( fd, PIOCPSINFO, &prp ) < 0 )
{
perror( "ioctl" );
exit( 5 );
}
if ( ioctl( fd, PIOCSTATUS, &prs ) < 0 )
{
perror( "ioctl" );
exit( 7 );
}
if ( counter >; 9 )
{
fprintf( stdout, " ID\tIMAGE\t\tRSS\t\tHEAP\t\tSTACK\n" );
counter = 0;
}
fprintf( stdout, "%u\t%-9u\t%-9u\t%-15u\t%-15u\n", pid,
( unsigned int )prp.pr_bysize, ( unsigned int )prp.pr_byrssize,
( unsigned int )prs.pr_brksize, ( unsigned int )prs.pr_stksize );
counter++;
} /* end of getInfo */
--------------------------------------------------------------------------
4.2 Solaris下如何獲知CPU速率
A: Philip Brown <phil+s3@bolthole.no-bots.com>;
psrinfo -v
psrinfo | grep on-line | wc -l 簡單給出CPU數(shù)目
A: scz <scz@nsfocus.com>;
# /usr/platform/`uname -i`/sbin/prtdiag -v
# /usr/platform/`uname -m`/sbin/prtdiag -v
# /usr/bin/netstat -k cpu_info0
A: Tony Walton <tony.walton@uk.sun.com>;
如果你裝了Sun Workshop,還可以嘗試fpversion命令
# /opt/SUNWspro/bin/fpversion
A SPARC-based CPU is available.
CPU's clock rate appears to be approximately 266.1 MHz.
Kernel says CPU's clock rate is 270.0 MHz.
Kernel says main memory's clock rate is 90.0 MHz.
Sun-4 floating-point controller version 0 found.
An UltraSPARC chip is available.
FPU's frequency appears to be approximately 277.1 MHz.
Use "-xtarget=ultra2i -xcache=16/32/1:256/64/1" code-generation option.
Hostid = 0x80BC3CB3.
#
4.3 如何編程獲取Solaris系統(tǒng)當(dāng)前內(nèi)存大小
Q: 如何編程(或者有什么現(xiàn)成命令)獲取Solaris系統(tǒng)當(dāng)前內(nèi)存大?
A: Nithyanandham <m.nithyanandham@blr.spcnl.co.in>;
幾個現(xiàn)成命令
/usr/platform/`uname -m`/sbin/prtdiag -v | grep Memory
prtconf -v | grep Memory
如果裝了GNU top,也可以直接用top命令看到。
D: scz <scz@nsfocus.com>;
truss prtconf的輸出中有如下內(nèi)容
sysconfig(_CONFIG_PAGESIZE) = 8192
sysconfig(_CONFIG_PHYS_PAGES) = 16384
Memory size: 128 Megabytes
# /usr/ccs/bin/nm -nx /dev/ksyms | grep "|sysconfig$"
10626] |0x0000100ec110|0x0000000001bc|FUNC |GLOB |0 |ABS |sysconfig
# find /usr/include -type f -name "*.h" | xargs grep -l _CONFIG_PAGESIZE
/usr/include/sys/sysconfig.h
# vi -R /usr/include/sys/sysconfig.h
/*
* cmd values for _sysconfig system call.
* WARNING: This is an undocumented system call,
* therefore future compatibility can not
* guaranteed.
*/
#define _CONFIG_PAGESIZE 6 /* system page size */
#define _CONFIG_PHYS_PAGES 26 /* phys mem installed in pages */
參看sysconf(3C)手冊頁。
_SC_PAGESIZE
_SC_PAGE_SIZE
_SC_PHYS_PAGES
A: Casper Dik <Casper.Dik@Holland.Sun.COM>;
--------------------------------------------------------------------------
/*
* Program to determine the size installed physical memory on Suns.
*
* Casper Dik.
*/
#define MEGABYTE 0x00100000
#define MAXMEM 0x7ff00000
#define THEMEM "/dev/mem"
#include <stdio.h>;
#include <fcntl.h>;
#include <sys/types.h>;
#include <unistd.h>;
int main ( int argc, char * argv[] )
{
int fd = open( THEMEM, O_RDONLY );
char c;
unsigned long pos, mapstart = 0;
int totmb = 0;
if ( fd == -1 )
{
perror( THEMEM );
exit( 1 );
}
for ( pos = 0; pos < MAXMEM; pos += MEGABYTE )
{
if (lseek( fd, pos, 0 ) == -1 )
{
perror( "lseek" );
exit( 1 );
}
if ( read( fd, &c, 1 ) == -1 )
{
int size = ( pos - mapstart ) / MEGABYTE;
if ( size != 0 )
{
printf( "found %3d MB starting at 0x%p\n", size, ( void * )mapst
art );
totmb += size;
}
mapstart = pos + MEGABYTE; /* start of next possible mapping */
}
}
printf( "Total memory size: %d MB\n", totmb );
exit( 0 );
}
--------------------------------------------------------------------------
由于需要讀訪問/dev/mem,普通用戶用戶無法使用該程序。
5. 塊設(shè)備相關(guān)問題
5.1 CDROM設(shè)備究竟在哪里
Q: 為了mount光驅(qū),需要哪些包
A: SUNWvolr SUNWcstl SUNWcstlx
D: Dennis Clarke <dclarke@blastwave.com>;
1) su - root
2) /etc/init.d/volmgt stop
3) ls -1 /dev/dsk/c*s2
4) mount -F hsfs -o ro /dev/dsk/c0t6d0s2 /cdrom
或者
1) /etc/init.d/volmgt stop
2) /etc/init.d/volmgt start
3) volcheck
4) eject
觀察/etc/vold.conf
Q: 如何才能知道哪個設(shè)備文件對應(yīng)CDROM(c0t2d0s0?)。如果有一張光盤在CDROM里,
可以用df命令看到對應(yīng)的設(shè)備文件,但是沒有光盤在光驅(qū)里的時候呢?
A: /dev/sr0 是一個指向最終設(shè)備文件的符號鏈接,僅對SPARC有效,不包括x86
A: Logan Shaw <logan@cs.utexas.edu>;
$ uname -sri
SunOS 5.8 i86pc
$ ls -l /dev/sr*
lrwxrwxrwx /dev/sr0 ->; dsk/c1t0d0s2
$
我想x86下是一樣的
Q: E420R,Solaris 7 11/99,我從http://sunsolve.sun.com獲得一些補(bǔ)丁并安裝了,
結(jié)果現(xiàn)在我的光驅(qū)出問題了。似乎mount成功了,但是找不到文件,/etc/mnttab
中沒有任何有關(guān)光驅(qū)的信息,插入一張光盤會彈出一個文件管理器窗口,但是沒
有文件。
A: Danny Mann <dma@wwa.com>;
檢查是否打了如下Solaris 7內(nèi)核補(bǔ)丁106541-13和 -14。這兩個補(bǔ)丁有問題。解
決辦法是禁止vold,手工mount光驅(qū)。
A: rschicht@my-deja.com <rschicht@my-deja.com>;
試試volrmmount -d命令。用patchadd -p檢查是否安裝了補(bǔ)丁106541-14,訪問如
下鏈接
http://sunsolve.Sun.COM/pub-cgi/show.pl?target=patches/patch-access
獲取補(bǔ)丁106541-14的說明,閱讀NOTE 15。
A: 補(bǔ)丁106541-14的說明,NOTE 15
1. 首先禁止掉vold守護(hù)進(jìn)程
# /etc/init.d/volmgt stop
2. 手工mount光驅(qū)(設(shè)備文件名可能不同)
# /etc/mount -F hsfs -o ro /dev/dsk/c0t2d0s0 /cdrom
查看/etc/vfstab、/dev/dsk確認(rèn)光驅(qū)所在設(shè)備文件名。
5.2 如何彈出光驅(qū)
Q: 在安裝Oracle 8i時,系統(tǒng)提示插入第二張光盤,但是此時無法成功eject第一張
光盤,終端掛起,殺掉Oracle 8i的安裝進(jìn)程也無濟(jì)于事。唯一的辦法是reset。
A: Sergey Kurganov <mmerfi@home.com>;
下面的操作或許有所幫助
1) 終止卷管理器
# /etc/init.d/volmgt stop
2) unmount光驅(qū),手動eject
3) 重啟卷管理器
# /etc/init.d/volmgt start
D: plane@smth.org 2002-02-26 01:03
裝Oracle 9的時候,安裝文檔特意提醒要用絕對路徑才能換盤。
5.3 如何利用超級塊進(jìn)行恢復(fù)工作
Q: Sun工作站在reboot時掉電了,用安裝光盤啟動進(jìn)入單用戶模式,執(zhí)行fsck命令時
報錯
Stop-A
ok boot cdrom -s
INIT: SINGLE USER MODE
# fsck -o b=32 /dev/rdsk/c0t5d0s*
Alternate super block location: 32.
** /dev/rdsk/c0t5d0s0
BAD SUPER BLOCK: MAGIC NUMBER WRONG
USE AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION;
eg. fsck [-F ufs] -o b=# [special ...]
where # is the alternate super block. SEE fsck_ufs(1M).
Alternate super block location: 32.
** /dev/rdsk/c0t5d0s1
BAD SUPER BLOCK: MAGIC NUMBER WRONG
USE AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION;
eg. fsck [-F ufs] -o b=# [special ...]
where # is the alternate super block. SEE fsck_ufs(1M).
Alternate super block location: 32.
** /dev/rdsk/c0t5d0s2
BAD SUPER BLOCK: MAGIC NUMBER WRONG
USE AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION;
eg. fsck [-F ufs] -o b=# [special ...]
where # is the alternate super block. SEE fsck_ufs(1M).
Alternate super block location: 32.
A: Sree Mokkapati <sree@broadcom.com>;
正確的用法就在錯誤提示信息里,你應(yīng)該使用另外的超級塊進(jìn)行恢復(fù)工作,32僅
僅是常用備份超級塊之一。
fsck -F ufs -o b=32 device_name
此外如果想知道還有哪些備份超級塊可用,執(zhí)行
newfs -Nv device_name
先用df等命令確認(rèn)原始device_name。
D: scz <scz@nsfocus.com>; 2001-10-12 17:01 修訂
SPARC/Solaris的硬盤損壞多半是文件系統(tǒng)根區(qū)被破壞,并不需要拆卸硬盤到其他
機(jī)器上mount后fsck,找一張Solaris安裝光盤
Stop-A進(jìn)入OBP狀態(tài),在ok提示符下輸入
ok>; boot cdrom -s
進(jìn)入單用戶模式。此時原有根文件系統(tǒng)并未mount上來,也不需要mount原有根文
件系統(tǒng),直接
newfs -Nv /dev/rdsk/c0t0d0s0
找出原根文件系統(tǒng)所有備份超級塊號
fsck -y -F ufs -o b=<任一備份超級塊號>; /dev/rdsk/c0t0d0s0
這里假設(shè)原根文件系統(tǒng)的原始設(shè)備名是/dev/rdsk/c0t0d0s0。其他文件系統(tǒng)的原
始設(shè)備名可以在系統(tǒng)完好時 df -k 獲取,或者從/etc/vfstab中獲取信息。比如
/dev/rdsk/c0t0d0s0 /
/dev/rdsk/c0t0d0s6 /usr
/dev/rdsk/c0t0d0s7 /export/home
vfstab(4)解釋得很模糊,回頭我上www.google.com去找找其他資料。
The fsck pass value of 2 means that the file system will be checked,
but not sequentially
5.4 Solaris Root口令忘記了
Q: 忘記了root口令,怎么辦
A: Steve Menard <opsmaster@yahoo.com>;
啟動時按Stop-A進(jìn)入ok提示符
ok boot cdrom -s (放入啟動安裝光盤)
mount /dev/dsk/c0t0d0s0 /mnt (這里指定原根區(qū)對應(yīng)的原始設(shè)備名)
TERM=vt100;export TERM
vi /mnt/etc/shadow
刪除root口令加密串,比如
root:WxzL460hohWsU:10724::::::
刪除WxzL460hohWsU,確認(rèn)你還有8個冒號,重啟動
或者 /usr/sbin/reboot -- "cdrom -s"
A: Philip Brown <phil+s3@bolthole.no-bots.com>;
使用vi有很多麻煩的地方,可以考慮sed
mount /dev/dsk/c0t0d0s0 /mnt
sed 's/:WxzL460hohWsU:/::/' /mnt/etc/shadow >; s
mv s /mnt/etc/shadow
或者使用ed
mount /dev/dsk/c0t0d0s0 /mnt
ed /mnt/etc/shadow
1s/root:[^:]*:/root::/ (注意,前面是1,不是l)
w
q
5.5 如何使用fmthard
A: Seán Boran <sean@boran.com>;
如果希望對第二塊物理硬盤的分區(qū)與第一塊物理硬盤一樣,考慮fmthard和prtvtoc的
結(jié)合使用,要比手工format快得多。比如,第一塊物理硬盤是target 3,第二塊物理
硬盤是target 1,我們希望第二塊物理硬盤磁盤卷標(biāo)是"mirror",做如下操作:
/usr/sbin/prtvtoc /dev/rdsk/c0t3d0s2 | /usr/sbin/fmthard -n mirror -s - /dev/rds
k/c0t1d0s2
man -s 1M fmthard了解更多細(xì)節(jié)。
5.6 如何從光盤恢復(fù)Solaris 7的引導(dǎo)扇區(qū)
A: paranoid@bbs.tsinghua.edu.cn
在安裝盤里有一個tools目錄,進(jìn)去后有一個命令叫做installboot
A: melonm@bbs.tsinghua.edu.cn
比如
installboot /usr/platform/`uname -i`/lib/fs/ufs/bootblk /dev/rdsk/c0t1d0s0
5.7 Solaris支持類似微軟autorun.inf文件的功能嗎
Q: 我自己制作了一張光盤,同時用于Solaris和Windows。在Windows環(huán)境下,可以利
用autorun功能,當(dāng)插入光盤的時候自動調(diào)用喜愛的瀏覽器打開一個文件。不知道
Solaris 7/8下是否存在類似功能。
A: hakteng
是的,從Solaris 8(CDE version 1.4)開始支持類似功能了
o 創(chuàng)建一個名為"volstart"的腳本文件,比如
--------------------------------------------------------------------------
#! /bin/ksh
#
# This is a CD volume start script. This start script is designed
# to be automatically run when the CD is inserted into a Solaris
# system's CDrom drive.
#
# Note: not all Solaris systems have an auto volstart ability. If this
# CD is inserted into a CDrom drive of a Solaris system without the
# volstart ability, volstart can also be run manually by executing it
# from either the desktop's file manager or from a Unix command line.
full_name=$0
dir_name=`/usr/bin/dirname $full_name`
if [[ -x /usr/dt/bin/dtaction ]]; then
# Run the CDrom's installer program
/usr/dt/bin/dtaction Run $dir_name/installer
fi
--------------------------------------------------- |
|