從《長尾理論》想到的運維上面的一些事情

以前寫的,遷過來了。


從《長尾理論》想到的運維上面的一些事情

長尾理論1.0的書也看過,2.0買還是沒買也記不得了。今天上午工作的時候,突然想到了一些問題。長尾理論主要介紹,經典的2/8理論已經不適合互聯網的模式,互聯網的由於他的信息檢索方式,存儲方式,以及購物方式都發起了根本性的轉變,如同一本很久以前沒有賣掉的書,可能經過一些推銷,互聯網推銷成本還是比較低的,而且目的性也比較集中,可能就會把沉積多年的物品,通過互聯網方式賣出去。

===============================================================

下面是在網上找到的關於“長尾理論”

http://wiki.mbalib.com/wiki/%E9%95%BF%E5%B0%BE%E7%90%86%E8%AE%BA

舉例來說,我們常用的漢字實際上不多,但因出現頻次高,所以這些爲數不多的漢字佔據了上圖廣大的紅區;絕大部分的漢字難得一用,它們就屬於那長長的藍尾。 Chris認爲,只要存儲和流通的渠道足夠大,需求不旺或銷量不佳的產品共同佔據的市場份額就可以和那些數量不多的熱賣品所佔據的市場份額相匹敵甚至更大。

長尾市場也稱之爲“利基市場”。 “利基 ” 一詞是英文 “Niche” 的音譯,意譯爲 “ 壁龕 ” ,有拾遺補缺或見縫插針的意思。菲利普·科特勒《營銷管理》中給利基下的定義爲:利基是更窄地確定某些羣體,這是一個小市場並且它的需要沒有被服務好,或者說 “ 有獲取利益的基礎 ” 。

通過對市場的細分,企業集中力量於某個特定的目標市場,或嚴格針對一個細分市場,或重點經營一個產品和服務,創造出產品和服務優勢。

===============================================================

我應該沒記錯,這個理論是成立的,而且已經被廣大互聯網服務商所認可,下面就要談到我理解的關注點了,如果長尾理論是一條長長的尾巴,我可不可以理解成,用戶的極少數需求會被滿足,而且這種服務會支持到更長時間,很長,很長。這不會因爲新出一個應用後,就發生100%的轉變,肯定會有少部分的人還是會繼續原有系統,就如互聯網多NB,也沒有替換掉短信一樣。每個產品都有自己存在的理由和服務的用戶羣,未來就是有可能一直持續,持續到開發換了一波又一波,業務換了一波又一波。系統的各功能,會越積越多,系統的數量也會越來越多,但不會因爲功能的增加,運維人員也跟着比例的增加。老闆一般都不會這麼想的。

也就說是未來的系統可能是會越來越多,因爲產品只要還能提供利潤,業務輕易不會下線這些機器的,道理簡單的,只要來錢,他們纔不會的動的,一動可能這部分錢就沒有了。他纔不管你的底層是如何有問題,有風險。當然這裏存在一個溝通的維度,如果我們將事情的利弊講清楚,明白其中道理的業務也會同意,但這不是本文章要關注的。本文章要關注的如果我們可以預估到一些這種情況,我們如何來構建我們的基礎架構服務,如何來規劃我們的運維工作。

問題 “在長尾理論的環境下,運維工作要如何有效的開展”寫到現在才把問題拋出來,真心我的問題。:)

雖然背景我描述的很多,但真正要說到如何有效的開展,確也是沒有想過太多。如果非要拿出一些結論和說法,我們還得透過現象看本質。談一下我自己的看法,也只能說是看法。

長尾理論是非常小非常小的顆粒組成的,只要有足夠多的小顆粒,組成起來就是大市場,我們系統也要考慮到小顆粒意味的對系統的訪問壓力和設計壓力都不大。如果我們爲每個顆粒都都建立一套系統,可能這個顆粒開始的時候很大,我們爲他建立一套系統是正確的,但隨着時間的流逝,用戶的減少,不可能再有資源繼續投入了。終成了一個殭屍系統,誰也不知道,誰也不敢動。這裏面的涉及的開發職責暫不說,先說說運維怎麼規劃這件事情:

1)組件標準化,如一些系統組件如glibc版本,gcc 版本,PHP版本,mysql版本,儘量做到標準化,不使用特殊的擴展組件。
2)平臺標準化,在顆粒建設初期,或者在沒有建設系統的任務情況下,我們就應該着手考慮建立一個平臺,系統平臺可以整合多個業務平臺。多個顆粒系統都是很重要的。
3)系統集成化,如果我們要將多個子系統集成化在一起,我們需要考慮哪些關鍵指標,訪問壓力、系統壓力、流量壓力、擴容壓力、容災壓力、冗餘壓力、備份壓力,好多,好多。
4)升級有序化,運行的業務平臺多了,可能受限制的條件就多了,組件的升級工作可能將進行的異常緩慢,因爲要考慮的點多了,顧及多了,自然就會慢許多了。穩定是壓導一切的。
5)容災一體化,包括備機,備份、異地容災等,都是需要考慮的,因爲現在的服務都是面向全國的,電信,聯通互聯是永遠的痛,雙線機房也不是完美的解決方案。所以各區域都部署機器也是不得已的方案。

就是得玩標準化,集成化,平臺化,要不然多系統分散了,消耗人的精力也是非常巨大的。系統再沒有迭代不發展的情況下,下線是個非常漫長的事情。非常難,非常難,公司越大,越難搞。

準備在2項內容裏面多做些工作,考慮一下已有系統,包括其它業務的子系統,是可以建立一套基礎平臺,將一些訪問壓力小的業務,或者已經被長尾好久的系統都遷移到這臺平臺上,組織項目人員集中精力將這些系統進行標準化。同時也要考慮好3,5,1。至於4升級可能就很難很難,除非在初始遷移情況就進行一次,如果一旦進入這個平臺,再升級的可能性就又被降低了。
涉及的內容太多了,做成什麼樣,準備怎麼做,需要準備哪些東西,開發的支持資源有多少,遷移後的架構是什麼,遷移後是否還有擴容需求,標準是什麼。。。。。。。要準備的東西還很多。

最核心的問題是,1)在業務線運營時間越來越長,此業務給的支持不足夠多的背景下,但運營指標還是很高要求下。我們是否可以用更少的資源來進行運營,這樣可以給我們節約大量的人力和物力。
另一個擴展的問題是,如果新業務剛上線,機器數量少,無法建立比較完善的全國服務器佈局,是否也可以利用這個平臺進行運營初期的有效運行。也是要值得考慮的問題。

雖然事情說起來容易,但做起來難。還需要努力還做事情纔是真格的。

列一些我考慮的難點吧:
1)什麼業務及模塊適合此模型系統
2)判斷的標準什麼
3)日後維護複雜是否會增加,是否可以分離出來,基礎運維和應用運模,此對此模型
4)擴容指標,SET模型如何構建
5)多地部署應用,要考慮DB部署的情況
6)機器負載及最大可用性的評估
7)如果有效的進行系統的分離,避免因爲一個業務出現BUG,過渡消耗機器資源,導致其它業務模塊無法正常提供服務。
8)此業務系統搭建組件有哪些,如何提高高可用性,冗餘性是重要的課題。
9)如何說報業務開發將現有系統遷稱到此平臺上,因爲根據現在平臺基礎組件進行統一的升級工作。

主旨其實就是很簡單的一個道理~~一個產品的生命週期的尾端如何可運維(前同事送我的一句話。比我厲害啊)

BYW:自有業務的平臺化,跟開放開放平臺的平臺化,差異還是挺大的,自有業務都是已經存在多年,運營多年,開發放平臺是近一兩年再興趣的,所以標準制定的也比較完善。所以往大了想,應該有一個大平臺融合所有。從業務中把平臺剝離出來。但需要至少幾期工程纔可以,“路漫漫其修遠兮,吾將上下而求索”

php程序不能解析域名到IP

遷移程序到另一臺機器,OS一樣,apache,php一樣,但程序就是報連不上數據庫,在操作系統上ping,host,mysql,telnet都沒問題。

把這個域名放到/etc/hosts下面就沒問題,但用/etc/resolve.conf方式來查就行。下面是對這2種方式訪問的時候進行的strace,對apache進行strace比較頭痛,因爲初始的子進程特別多,你也不知道是哪個。所以需要改httpd.conf參數,將進程放到1-2個這樣就好監控了。當然這時候機器不能是線上的。

這兩個輸出的主要是右側對stat64(“/etc/resolve.conf”…..)後就沒有進行open這個文件,這是關鍵點,也是疑點,說明httpd進程,根本沒有去讀這個文件,自然解析不到相關的數據名域名。

這時候其實也不知道如何入手,具體怎麼樣的過程都忘記了,就是查到了httpd進程好象沒有加載libnss_dns-2.4.s0,這個so是屬於系統的glibc庫的,不太可能有問題,問題在於httpd爲什麼不加載他,仔細看了strace說實話也沒啥結果。

發現httpd進程初始的會讀一些庫,當然這是通過strace根本的結果,但不是啓動後,是在開始啓動的時候,如:

strace ./apache -k start

發現httpd會讀好多目錄的下的libnss_*.so,當然也包括libnss_dns-2.4.so,我就把/lib/libnss* 複製到/usr/local/lib/下面

各種ldconfig,發現還不生效,過了一會又試發現問題解決了。每次在頁面執行的時候,再系統上lsof | grep libnss,發現httpd進程加讀這個libnss_dns-2.4.so,只要讀了這個庫,php在apache裏面就可以正常解析域名。

下面是解決之後再觀察httpd進程啓動的加載過程的

strace ./apache -k start

11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/i686/sse2/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/i686/sse2/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/i686/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/i686/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/sse2/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/sse2/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/tls/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/i686/sse2/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/i686/sse2/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/i686/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/i686/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/sse2/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/sse2/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/nosegneg/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
11:41:44 open(“/usr/local/httpd-2.0.59/lib/libnss_dns.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)

上面是要去/usr/local/httpd-2.0.59/lib/下面去讀一大堆的libnss*的庫,實際上這些庫都是在/lib/下面。將libnss*複製到/usr/local/lib下後
11:41:44 open(“/etc/ld.so.cache”, O_RDONLY) = 18
11:41:44 fstat64(18, {st_mode=S_IFREG|0644, st_size=37181, …}) = 0
11:41:44 mmap2(NULL, 37181, PROT_READ, MAP_PRIVATE, 18, 0) = 0xb7727000
11:41:44 close(18)                      = 0
11:41:44 open(“/usr/local/lib/libnss_dns.so.2″, O_RDONLY) = 18

httpd就可以open 上庫了。
11:41:44 read(18, “177ELF111331@16004360B004 n( 356004004004@1@15433453345334532323411270527055201354>354N354N230123416202?OO340340644t1t1t1 444″…, 512) = 512
11:41:44 fstat64(18, {st_mode=S_IFREG|0755, st_size=21427, …}) = 0
11:41:44 mmap2(NULL, 20616, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 18, 0) = 0xb7034000
11:41:44 madvise(0xb7034000, 20616, MADV_SEQUENTIAL|0×1) = 0
11:41:44 mmap2(0xb7038000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 18, 0×3) = 0xb7038000
11:41:44 close(18)                      = 0
11:41:44 munmap(0xb7727000, 37181)      = 0
11:41:44 time(NULL)                     = 1340768504

讀完libnss_dns庫後,httpd會去讀/etc/resolv.conf。然後就可以去連接DNS解析了
11:41:44 stat64(“/etc/resolv.conf”, {st_mode=S_IFREG|0755, st_size=61, …}) = 0
11:41:44 open(“/etc/resolv.conf”, O_RDONLY) = 18
11:41:44 fstat64(18, {st_mode=S_IFREG|0755, st_size=61, …}) = 0
11:41:44 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7730000
11:41:44 read(18, “search sitennameserver 172.27.x.xnnameserver 172.17.x.xn”, 4096) = 61
11:41:44 read(18, “”, 4096)             = 0
11:41:44 close(18)                      = 0
11:41:44 munmap(0xb7730000, 4096)       = 0
11:41:44 gettimeofday({1340768504, 899255}, NULL) = 0
11:41:44 socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 18
11:41:44 connect(18, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(“172.27.x.x”)}, 28) = 0  <–這一條是去連接DNS服務器
11:41:44 fcntl64(18, F_GETFL)           = 0×2 (flags O_RDWR)
11:41:44 fcntl64(18, F_SETFL, O_RDWR|O_NONBLOCK) = 0


這樣就解決了,也只是把庫複製到/usr/local/lib下面,httpd就可以讀取了。這樣就自動可以解析域名了。

環境是:suse 10sp2 32bit gcc 4.1.2




web模型和mail模型一點小感悟

早上在看書,突然想到,web模型和mail郵件模型很重要的一點是,數據一個關鍵的屬性,“屬主”不一樣,直接導致整體的策略及業務不一樣。數據的屬性不一樣,體現在數據是屬性跟用戶的訪問是否有強一致關聯,web不是強致性,mail確實強一致,這是導致必須用兩種思維去考慮架構和設計。先記下來,怕忘記
原來一直在想,我老是講web模型簡單,這簡單,那簡單(相對簡單,絕對不簡單),一講起來絕也無從下手,今天早上突然想到,記錄了上面的話。不管什麼模型,他最終會由數據來體現出來,只有數據才能被用戶所感知,包括視覺,聽覺,我這裏都統一叫作數據。那數據就應該有一些特性,比如擴展性,一致性。只是講我們在不同的視角,看到的數據特性爲我們思想所用的時候,體現出來的數據的特徵不一樣。如兩個模型的對比,我主要從用戶訪問角度來考慮。當然再提高一點層次,我們就得看到業務的不同了,不管是個人郵件,或企業郵件,他從被被發明到現在的應用,總脫離不了他的核心特點,每個會話數據傳輸獨立的性,用戶訪問自有獨立空間,數據訪問空間的隔離性。
而web應用,他的產生和今天的擴大化應用(SNaS)已經變化比較大了,但他有獨佔也比較明顯,如廣播性,非強制每用戶會話數據獨立性。

而數據這些顯著的特點是對比,我們可以清晰的看到兩種主流應用的特點,如果在能將自己知識,經驗在不同的模型中轉換是很簡單確實又很艱難的問題,簡單講:我是從結構往下走的,他們都面對的存儲,索引,網絡等基本元素,只要將這些概念理解深入,掌握到位,其實不管什麼模型都是建立在“原子”之上的,這就是我講的簡單。難的地方,如果想做領導,或架構師,不能只考慮非常底層的東西,需要站的有高度有視野,但兩種模型的差異放在那裏,我們只能抽象一層考慮,如他們的數據模型是什麼,他們的訪問模型是什麼(多地訪問) ,再考慮不同類別東西的時候,我到現在的理解就是,理解不了的東西就抽象出來,再理解不了的東西再抽象出來。這樣最後可能只會變成哲學裏面講的“物持和意識”,這個東西說多了就容易不物質了,但我們如果用一些方法去理解不同的業務,至少我沒有想到好的辦法,除了抽象應該是沒有其它辦法了。

這裏有一個提升的點,也可能是我的年紀已經有點大了,不想再研究底層的東西,哈,其實也不是。如果我們對兩種模型號抽象完之後,就停手,好好理解一下,畢竟任何一種技術都是有缺陷的,我們平時解決不了的問題,可能就是我們沒有好好理解本質的東西,理解之後我們將可以將相互的經驗來借鑑,有人可能說一個是postfix,一個是apache,別忘記我們是從更高層抽象來看,他們有本質的東西,如全國性訪問速度,高可靠性。都是可以互相學習的,這可能纔是最終我們抽象出來想看的東西,“互相學習,互相借鑑”。


好了就寫這麼多的吧,也是一時心血來潮,該收拾一下,趕班車去了。

fastyu

2012.6.28 晨

微博上遇到的幾篇好文章,分享一下

作者是鄧草原

http://weibo.com/dcaoyuan


這樣設計的結果,你可能會發現*核心*實體映射到數據表後更象一個記錄了本團塊內實體的目錄,這樣的設計是正確的,因爲,一、另一個團塊內的實體如果想查找這個團塊的實體,首先就是查這個目錄;二、在分佈式系統中,目錄是最重要的;三、一個層次化甚至分佈式系統的核心構架就是一級一級目錄。

rand,srand學習

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,seed;
printf(“this porgram displays the first five values of “”rand.n”);

for (;;) {
 for (i=0;i<5;i++)
       printf(“%d “,rand());

printf(“nnt”);
printf(“enter new seed value (o to terminate):”);
scanf(“%d”,&seed);
if (seed==0)
       break;
srand(seed);
}

return 0;

}

rand函數和srand函數都是用來生成隨機數的,rand函數會返回一個0~RAND_MAX(stdlib.h定義的宏)之間的數,rand函數是不承受機的,但這些數是由“種子”值產生的,每個種子值確定了一個特定的僞隨機序列。srand是可以爲rand函數提供種子的,意思是rand函數需要的種子是可以變化的了,但需要srand來提供。


 # ./a.out
this porgram displays the first five values of rand.
1804289383 846930886 1681692777 1714636915 1957747793     A

tenter new seed value (o to terminate):3
1205554746 483147985 844158168 953350440 612121425     B

tenter new seed value (o to terminate):2
1505335290 1738766719 190686788 260874575 747983061

tenter new seed value (o to terminate):3
1205554746 483147985 844158168 953350440 612121425     B

tenter new seed value (o to terminate):

上面是初始會生成幾個隨機數,但重新輸入種子3 後,會產生新的隨機數,但再次輸入3後就會再次產生相同的隨機數(B行就說明了問題)
 # ./a.out
this porgram displays the first five values of rand.
1804289383 846930886 1681692777 1714636915 1957747793 A

tenter new seed value (o to terminate):3
1205554746 483147985 844158168 953350440 612121425

tenter new seed value (o to terminate):
#

再次執行這個程序由於初始的承受機的種子初始是1所以開始顯示的隨機數還是一樣的。下面的例子也說明,我即使給srand輸入1,顯示的跟程序初始執行的結果是一樣的。

# ./a.out
this porgram displays the first five values of rand.
1804289383 846930886 1681692777 1714636915 1957747793

tenter new seed value (o to terminate):1
1804289383 846930886 1681692777 1714636915 1957747793

tenter new seed value (o to terminate):

dbm簡單學習

編習例子apue的20-1.c

#include <apue.h>
#include “apue_db.h”
#include <fcntl.h>

int main(void)
{
DBHANDLE db;

if ((db=db_open(“db4″,O_RDWR|O_CREAT|O_TRUNC,FILE_MODE))==NULL)
       err_sys(“db_open error”);

if (db_store(db,”alpha”,”data1″,DB_INSERT)!=0)
       err_quit(“db_store error for alpha”);
if (db_store(db,”beta”,”data for beta”,DB_INSERT)!=0)
       err_quit(“db_store error for beta”);
if (db_store(db,”gamma”,”recordd3″,DB_INSERT)!=0)
       err_quit(“db_store error for gamma”);

db_close(db);

exit(0);

}


看apue_db.h還是比較簡單的,

more /usr/include/apue_db.h
#ifndef _APUE_DB_H
#define _APUE_DB_H

typedef void *  DBHANDLE;

DBHANDLE  db_open(const char *, int, …);
void      db_close(DBHANDLE);
char     *db_fetch(DBHANDLE, const char *);
int       db_store(DBHANDLE, const char *, const char *, int);
int       db_delete(DBHANDLE, const char *);
void      db_rewind(DBHANDLE);
char     *db_nextrec(DBHANDLE, char *);

/*
* Flags for db_store().
*/
#define DB_INSERT          1    /* insert new record only */
#define DB_REPLACE         2    /* replace existing record */
#define DB_STORE           3    /* replace or insert */

/*
* Implementation limits.
*/
#define IDXLEN_MIN         6    /* key, sep, start, sep, length, n */
#define IDXLEN_MAX      1024    /* arbitrary */
#define DATLEN_MIN         2    /* data byte, newline */
#define DATLEN_MAX      1024    /* arbitrary */

#endif /* _APUE_DB_H */

但編譯的時候有問題

# gcc 20-1.c
/tmp/ccc3stZr.o: In function `main’:
20-1.c:(.text+0×382): undefined reference to `db_open’
20-1.c:(.text+0x3ba): undefined reference to `db_store’
20-1.c:(.text+0x3ed): undefined reference to `db_store’
20-1.c:(.text+0×420): undefined reference to `db_store’
20-1.c:(.text+0x43b): undefined reference to `db_close’
collect2: ld returned 1 exit status

在apue_db.h添加一個,把apue包裏的db.c複製到/usr/include裏面

#include “db.c”


# more 20-1.c
#include <apue.h>
#include “apue_db.h”
#include <fcntl.h>

int main(void)
{
DBHANDLE db;

if ((db=db_open(“db4″,O_RDWR|O_CREAT|O_TRUNC,FILE_MODE))==NULL)
       err_sys(“db_open error”);

if (db_store(db,”alpha”,”data1″,DB_INSERT)!=0)
       err_quit(“db_store error for alpha”);
if (db_store(db,”beta”,”data for beta”,DB_INSERT)!=0)
       err_quit(“db_store error for beta”);
if (db_store(db,”gamma”,”recordd3″,DB_INSERT)!=0)
       err_quit(“db_store error for gamma”);

db_close(db);

exit(0);

}
 # l

再編譯還是有問題

# cd ../../learn/
# gcc 20-1.c
/tmp/ccIedg2e.o: In function `db_open’:
20-1.c:(.text+0x54e): undefined reference to `lock_reg’
20-1.c:(.text+0x68b): undefined reference to `lock_reg’
/tmp/ccIedg2e.o: In function `db_fetch’:
20-1.c:(.text+0x8b9): undefined reference to `lock_reg’
/tmp/ccIedg2e.o: In function `_db_find_and_lock’:
20-1.c:(.text+0x94c): undefined reference to `lock_reg’
20-1.c:(.text+0×995): undefined reference to `lock_reg’
/tmp/ccIedg2e.o:20-1.c:(.text+0xe98): more undefined references to `lock_reg’ follow
collect2: ld returned 1 exit status
 #

說找到lock_reg,發現在apue包裏面有lock_reg.c將他複製到/usr/include下面,然後修改apue.h

#include “lockreg.c”

添加這麼一行。再編譯就過去了。

執行程序

# strace ./a.out
execve(“./a.out”, ["./a.out"], [/* 58 vars */]) = 0
brk(0)                                  = 0x804c000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f39000
access(“/etc/ld.so.preload”, R_OK)      = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY)      = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=36952, …}) = 0
mmap2(NULL, 36952, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb7f2f000
close(4)                                = 0
open(“/lib/libc.so.6″, O_RDONLY)        = 4
read(4, “177ELF111331340Y1″…, 512) = 512
fstat64(4, {st_mode=S_IFREG|0755, st_size=1548470, …}) = 0
mmap2(NULL, 1312188, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0xb7dee000
madvise(0xb7dee000, 1312188, MADV_SEQUENTIAL|0×1) = 0
mmap2(0xb7f28000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0×139) = 0xb7f28000
mmap2(0xb7f2c000, 9660, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f2c000
close(4)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ded000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7ded6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7f28000, 8192, PROT_READ)   = 0
munmap(0xb7f2f000, 36952)               = 0
brk(0)                                  = 0x804c000
brk(0x806d000)                          = 0x806d000
open(“db4.idx”, O_RDWR|O_CREAT|O_TRUNC, 0644) = 4   <–索引文件
open(“db4.dat”, O_RDWR|O_CREAT|O_TRUNC, 0644) = 5   <-數據文件
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
fstat64(4, {st_mode=S_IFREG|0644, st_size=0, …}) = 0
write(4, “     0     0     0     0     0  “…, 829) = 829
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
lseek(4, 829, SEEK_SET)                 = 829
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=264, len=1}) = 0
lseek(4, 264, SEEK_SET)                 = 264
read(4, “     0″, 6)                    = 6
lseek(4, 264, SEEK_SET)                 = 264
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}) = 0
lseek(4, 0, SEEK_SET)                   = 0
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=1}) = 0
fcntl64(5, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
lseek(5, 0, SEEK_END)                   = 0
writev(5, [{"data1", 5}, {"n", 1}], 2) = 6
fcntl64(5, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 0, SEEK_END)                   = 829
writev(4, [{"     0  10", 10}, {"alpha:0:6n", 10}], 2) = 20
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 264, SEEK_SET)                 = 264
write(4, “   829″, 6)                   = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=264, len=1}) = 0
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=468, len=1}) = 0
lseek(4, 468, SEEK_SET)                 = 468
read(4, “     0″, 6)                    = 6
lseek(4, 468, SEEK_SET)                 = 468
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}) = 0
lseek(4, 0, SEEK_SET)                   = 0
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=1}) = 0
fcntl64(5, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
lseek(5, 0, SEEK_END)                   = 6
writev(5, [{"data for beta", 13}, {"n", 1}], 2) = 14
fcntl64(5, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 0, SEEK_END)                   = 849
writev(4, [{"     0  10", 10}, {"beta:6:14n", 10}], 2) = 20
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 468, SEEK_SET)                 = 468
write(4, “   849″, 6)                   = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=468, len=1}) = 0
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=234, len=1}) = 0
lseek(4, 234, SEEK_SET)                 = 234
read(4, “     0″, 6)                    = 6
lseek(4, 234, SEEK_SET)                 = 234
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}) = 0
lseek(4, 0, SEEK_SET)                   = 0
read(4, “     0″, 6)                    = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=1}) = 0
fcntl64(5, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
lseek(5, 0, SEEK_END)                   = 20
writev(5, [{"recordd3", 8}, {"n", 1}], 2) = 9
fcntl64(5, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
fcntl64(4, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 0, SEEK_END)                   = 869
writev(4, [{"     0  11", 10}, {"gamma:20:9n", 11}], 2) = 21
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=829, len=0}) = 0
lseek(4, 234, SEEK_SET)                 = 234
write(4, “   869″, 6)                   = 6
fcntl64(4, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=234, len=1}) = 0
close(4)                                = 0
close(5)                                = 0
exit_group(0)                           = ?
Process 6267 detached
#



# more db4.dat
data1
data for beta
recordd3
# more db4.idx
    0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0   869     0     0     0     0
  829     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0     0     0   849     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0
    0  10alpha:0:6
    0  10beta:6:14
    0  11gamma:20:9
# file db4.dat
db4.dat: ASCII text
 # file db4.idx
db4.idx: ASCII text, with very long lines
 #


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章