C高階編程

### main函數(shù)執(zhí)行之前做了什么?(iOS)

&? dyld 是Apple 的動(dòng)態(tài)鏈接器贡定;在 xnu 內(nèi)核為程序啟動(dòng)做好準(zhǔn)備后绷跑,就會(huì)將 PC 控制權(quán)交給 dyld 負(fù)責(zé)剩下的工作 (dyld 是運(yùn)行在 用戶態(tài)的, 這里由 內(nèi)核態(tài) 切到了用戶態(tài))乎完。

1)dyld 開(kāi)始將程序二進(jìn)制文件初始化

2)交由ImageLoader 讀取 image辱揭,其中包含了我們的類(lèi)盾沫,方法等各種符號(hào)(Class、Protocol 闯传、Selector谨朝、 IMP)

3)由于runtime 向dyld 綁定了回調(diào),當(dāng)image加載到內(nèi)存后甥绿,dyld會(huì)通知runtime進(jìn)行處理

4)runtime 接手后調(diào)用map_images做解析和處理

5)接下來(lái)load_images 中調(diào)用call_load_methods方法字币,遍歷所有加載進(jìn)來(lái)的Class,按繼承層次依次調(diào)用Class的+load和其他Category的+load方法

6)至此 所有的信息都被加載到內(nèi)存中

7)最后dyld調(diào)用真正的main函數(shù)

注意:dyld會(huì)緩存上一次把信息加載內(nèi)存的緩存妹窖,所以第二次比第一次啟動(dòng)快一點(diǎn)


### KVO實(shí)現(xiàn)原理

1.KVO是基于runtime機(jī)制實(shí)現(xiàn)的

2.當(dāng)某個(gè)類(lèi)的屬性對(duì)象第一次被觀察時(shí)纬朝,系統(tǒng)就會(huì)在運(yùn)行期動(dòng)態(tài)地創(chuàng)建該類(lèi)的一個(gè)派生類(lèi),在這個(gè)派生類(lèi)中重寫(xiě)基類(lèi)中任何被觀察屬性的setter 方法骄呼。派生類(lèi)在被重寫(xiě)的setter方法內(nèi)實(shí)現(xiàn)真正的通知機(jī)制

3.如果原類(lèi)為Person共苛,那么生成的派生類(lèi)名為NSKVONotifying_Person

4.每個(gè)類(lèi)對(duì)象中都有一個(gè)isa指針指向當(dāng)前類(lèi)判没,當(dāng)一個(gè)類(lèi)對(duì)象的第一次被觀察,那么系統(tǒng)會(huì)偷偷將isa指針指向動(dòng)態(tài)生成的派生類(lèi)隅茎,從而在給被監(jiān)控屬性賦值時(shí)執(zhí)行的是派生類(lèi)的setter方法

5.鍵值觀察通知依賴(lài)于NSObject 的兩個(gè)方法: willChangeValueForKey: 和 didChangevlueForKey:澄峰;在一個(gè)被觀察屬性發(fā)生改變之前, willChangeValueForKey:一定會(huì)被調(diào)用辟犀,這就 會(huì)記錄舊的值俏竞。而當(dāng)改變發(fā)生后,didChangeValueForKey:會(huì)被調(diào)用堂竟,繼而 observeValueForKey:ofObject:change:context: 也會(huì)被調(diào)用魂毁。


### ASCII碼表的一般規(guī)律

& 16進(jìn)制的0x30到0x39表示數(shù)字0到數(shù)字9;

& 16進(jìn)制的0x61到0x7A表示小寫(xiě)字母a到z;

& 16進(jìn)制的0x41到0x5A表示大寫(xiě)字母A到Z;

記住: jpg的頭部是<ffd8ffe0>? png的頭部是<89504e47>


### TCP的幾種狀態(tài)

在TCP層,有個(gè)FLAGS字段出嘹,這個(gè)字段有以下幾個(gè)標(biāo)識(shí):SYN, FIN, ACK, PSH, RST, URG.

其中席楚,對(duì)于我們?nèi)粘5姆治鲇杏玫木褪乔懊娴奈鍌€(gè)字段。

它們的含義是:

SYN表示建立連接税稼,

FIN表示關(guān)閉連接烦秩,

ACK表示響應(yīng),

PSH表示有 DATA數(shù)據(jù)傳輸郎仆,

RST表示連接重置只祠。


### 信號(hào)量

dispatch_semaphore的使用場(chǎng)景是處理并發(fā)控制.

dispatch_semaphore_create => 創(chuàng)建一個(gè)信號(hào)量

dispatch_semaphore_signal => 發(fā)送一個(gè)信號(hào)

dispatch_semaphore_wait => 等待信號(hào)

& 系統(tǒng)中規(guī)定當(dāng)信號(hào)量值為0時(shí),必須等待扰肌,知道信號(hào)量值不為零才能繼續(xù)操作抛寝。?

我們的信號(hào)量也可以實(shí)現(xiàn)同樣的功能。 首先狡耻,創(chuàng)建一個(gè)信號(hào)量墩剖。 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 創(chuàng)建方法里會(huì)傳入一個(gè)long型的參數(shù),這個(gè)東西你可以想象是一個(gè)庫(kù)存夷狰。有了庫(kù)存才可以出貨岭皂。 dispatch_semaphore_wait,就是每運(yùn)行一次沼头,會(huì)先清一個(gè)庫(kù)存爷绘,如果庫(kù)存為0,那么根據(jù)傳入的等待時(shí)間进倍,決定等待增加庫(kù)存的時(shí)間土至,如果設(shè)置為DISPATCH_TIME_FOREVER,那么意思就是永久等待增加庫(kù)存,否則就永遠(yuǎn)不往下面走猾昆。

dispatch_semaphore_signal陶因,就是每運(yùn)行一次,增加一個(gè)庫(kù)存.

// 某個(gè)信號(hào)進(jìn)行等待垂蜗, timeout:等待時(shí)間楷扬,永遠(yuǎn)等待為 DISPATCH_TIME_FOREVER

dispatch_semaphore_wait(<#dispatch_semaphore_t dsema#>, <#dispatch_time_t timeout#>)

等待信號(hào)解幽,具體操作是首先判斷信號(hào)量desema是否大于0,如果大于0就減掉1個(gè)信號(hào)烘苹,往下執(zhí)行躲株;

如果等于0函數(shù)就阻塞該線程等待timeout(注意timeout類(lèi)型為dispatch_time_t)時(shí),其所處線程自動(dòng)執(zhí)行其后的語(yǔ)句镣衡。


### TCP連接的三次握手

第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器霜定,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn)廊鸥;

第二次握手:服務(wù)器收到syn包望浩,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包黍图,即SYN+ACK包曾雕,此時(shí)服務(wù)器進(jìn)入SYN+RECV狀態(tài)奴烙;

第三次握手:客戶端收到服務(wù)器的SYN+ACK包助被,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此發(fā)送完畢切诀,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài)揩环,完成三次狀態(tài)。


### 字典實(shí)現(xiàn)原理

一:字典原理

NSDictionary(字典)是使用hash表來(lái)實(shí)現(xiàn)key和value之間的映射和存儲(chǔ)的

方法:-?(void)setObject:(id)anObject?forKey:(id)aKey;

Objective-C中的字典N(xiāo)SDictionary底層其實(shí)是一個(gè)哈希表

二:哈希原理

散列表(Hash table幅虑,也叫哈希表)丰滑,是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō)倒庵,它通過(guò)把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄褒墨,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù)擎宝,存放記錄的數(shù)組叫做散列表郁妈。

給定表M,存在函數(shù)f(key)绍申,對(duì)任意給定的關(guān)鍵字值key噩咪,代入函數(shù)后若能得到包含該關(guān)鍵字的記錄在表中的地址,則稱(chēng)表M為哈希(Hash)表极阅,函數(shù)f(key)為哈希(Hash) 函數(shù)胃碾。

哈希概念:哈希表的本質(zhì)是一個(gè)數(shù)組,數(shù)組中每一個(gè)元素稱(chēng)為一個(gè)箱子(bin)筋搏,箱子中存放的是鍵值對(duì)仆百。

三:哈希存儲(chǔ)過(guò)程

1.根據(jù) key 計(jì)算出它的哈希值 h。

2.假設(shè)箱子的個(gè)數(shù)為 n奔脐,那么這個(gè)鍵值對(duì)應(yīng)該放在第 (h % n) 個(gè)箱子中俄周。

3.如果該箱子中已經(jīng)有了鍵值對(duì)栏账,就使用開(kāi)放尋址法或者拉鏈法解決沖突。

在使用拉鏈法解決哈希沖突時(shí)栈源,每個(gè)箱子其實(shí)是一個(gè)鏈表挡爵,屬于同一個(gè)箱子的所有鍵值對(duì)都會(huì)排列在鏈表中。

哈希表還有一個(gè)重要的屬性: 負(fù)載因子(load factor)甚垦,它用來(lái)衡量哈希表的空/滿程度茶鹃,一定程度上也可以體現(xiàn)查詢(xún)的效率,計(jì)算公式為:

負(fù)載因子 = 總鍵值對(duì)數(shù) / 箱子個(gè)數(shù)

負(fù)載因子越大艰亮,意味著哈希表越滿闭翩,越容易導(dǎo)致沖突,性能也就越低迄埃。因此疗韵,一般來(lái)說(shuō),當(dāng)負(fù)載因子大于某個(gè)常數(shù)(可能是 1侄非,或者 0.75 等)時(shí)蕉汪,哈希表將自動(dòng)擴(kuò)容。

哈希表在自動(dòng)擴(kuò)容時(shí)逞怨,一般會(huì)創(chuàng)建兩倍于原來(lái)個(gè)數(shù)的箱子者疤,因此即使 key 的哈希值不變,對(duì)箱子個(gè)數(shù)取余的結(jié)果也會(huì)發(fā)生改變叠赦,因此所有鍵值對(duì)的存放位置都有可能發(fā)生改變驹马,這個(gè)過(guò)程也稱(chēng)為重哈希(rehash)。

哈希表的擴(kuò)容并不總是能夠有效解決負(fù)載因子過(guò)大的問(wèn)題除秀。假設(shè)所有 key 的哈希值都一樣糯累,那么即使擴(kuò)容以后他們的位置也不會(huì)變化。雖然負(fù)載因子會(huì)降低册踩,但實(shí)際存儲(chǔ)在每個(gè)箱子中的鏈表長(zhǎng)度并不發(fā)生改變泳姐,因此也就不能提高哈希表的查詢(xún)性能。

基于以上總結(jié)棍好,細(xì)心的朋友可能會(huì)發(fā)現(xiàn)哈希表的兩個(gè)問(wèn)題:

1.如果哈希表中本來(lái)箱子就比較多仗岸,擴(kuò)容時(shí)需要重新哈希并移動(dòng)數(shù)據(jù),性能影響較大借笙。

2.如果哈希函數(shù)設(shè)計(jì)不合理扒怖,哈希表在極端情況下會(huì)變成線性表,性能極低业稼。

HashMap 的實(shí)例有兩個(gè)參數(shù)影響其性能:初始容量和加載因子盗痒。容量是哈希表中桶的數(shù)量,初始容量只是哈希表在創(chuàng)建時(shí)的容量。加載因子 是哈希表在其容量自動(dòng)增加之前可以達(dá)到多滿的一種尺度俯邓。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時(shí)骡楼,則要對(duì)該哈希表進(jìn)行 rehash 操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu)),從而哈希表將具有大約兩倍的桶數(shù)稽鞭。

通常鸟整,默認(rèn)加載因子 (.75) 在時(shí)間和空間成本上尋求一種折衷。加載因子過(guò)高雖然減少了空間開(kāi)銷(xiāo)朦蕴,但同時(shí)也增加了查詢(xún)成本(在大多數(shù) HashMap 類(lèi)的操作中篮条,包括 get 和 put 操作眉菱,都反映了這一點(diǎn))俱笛。在設(shè)置初始容量時(shí)應(yīng)該考慮到映射中所需的條目數(shù)及其加載因子,以便最大限度地減少 rehash 操作次數(shù)商玫。如果初始容量大于最大條目數(shù)除以加載因子疹娶,則不會(huì)發(fā)生 rehash 操作伴栓。

很多人都有這個(gè)疑問(wèn),為什么hashmap的數(shù)組初始化大小都是2的次方大小時(shí)雨饺,hashmap的效率最高钳垮,我以2的4次方舉例,來(lái)解釋一下為什么數(shù)組大小為2的冪時(shí)hashmap訪問(wèn)的性能最高沛膳。本文主要描述了HashMap的結(jié)構(gòu)扔枫,和hashmap中hash函數(shù)的實(shí)現(xiàn),以及該實(shí)現(xiàn)的特性锹安,同時(shí)描述了hashmap中resize帶來(lái)性能消耗的根本原因,以及將普通的域模型對(duì)象作為key的基本要求倚舀。尤其是hash函數(shù)的實(shí)現(xiàn)叹哭,可以說(shuō)是整個(gè)HashMap的精髓所在,只有真正理解了這個(gè)hash函數(shù)痕貌,才可以說(shuō)對(duì)HashMap有了一定的理解风罩。

① hashmap是用鏈地址法進(jìn)行處理,多個(gè)key 對(duì)應(yīng)于表中的一個(gè)索引位置的時(shí)候進(jìn)行鏈地址處理舵稠,hashmap其實(shí)就是一個(gè)數(shù)組+鏈表的形式超升。

② 當(dāng)有多個(gè)key的值相同時(shí),hashmap中只保存具有相同key的一個(gè)節(jié)點(diǎn)哺徊,也就是說(shuō)相同key的節(jié)點(diǎn)會(huì)進(jìn)行覆蓋室琢。

③在hashmap中查找一個(gè)值,需要兩次定位落追,先找到元素在數(shù)組的位置的鏈表上盈滴,然后在鏈表上查找,在HashMap中的第一次定位是由hash值確定的轿钠,第二次定位由key和hash值確定巢钓。

④節(jié)點(diǎn)在找到所在的鏈后病苗,插入鏈中是采用的是頭插法,也就是新節(jié)點(diǎn)都插在鏈表的頭部症汹。

⑤在hashmap中上圖左邊綠色的數(shù)組中也存放元素硫朦,新節(jié)點(diǎn)都是放在左邊的table中的,這個(gè)在上圖中為了形象的表現(xiàn)鏈表形式而沒(méi)有使用背镇。


### 結(jié)構(gòu)體字節(jié)大小問(wèn)題

原則1:數(shù)據(jù)成員對(duì)齊規(guī)則:結(jié)構(gòu)(struct或聯(lián)合union)的數(shù)據(jù)成員阵幸,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,

后面每個(gè)數(shù)據(jù)成員存儲(chǔ)的起始位置要從該成員(自身)大小的整數(shù)倍開(kāi)始(如int在32位機(jī)為4字節(jié)芽世,則要從4的整數(shù)倍地址開(kāi)始存儲(chǔ))挚赊。

原則2:結(jié)構(gòu)體作為成員:如果一個(gè)結(jié)構(gòu)里有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開(kāi)始存儲(chǔ)济瓢。

(struct a里存有struct b荠割,b里有char,int旺矾,double等元素蔑鹦,那b應(yīng)該從8的整數(shù)倍開(kāi)始存儲(chǔ)。)

原則3:計(jì)算工作:結(jié)構(gòu)體的總大小箕宙,也就是sizeof的結(jié)果嚎朽,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊柬帕。

例1:struct A{

???????????????????? int a;

???????????????????? double b;

???????????????????? float c;

??????????};

??????????????? struct B{

???????????????????? char e[2];

???????????????????? int f;

???????????????????? double g;

???????????????????? short h;

???????????????????? struct A i;

??????????????????? };

?????? sizeof(A) = 24; int為4哟忍,double為8,float為4陷寝,總長(zhǎng)為8的倍數(shù)锅很,補(bǔ)齊,所以整個(gè)A為24凤跑。

?????? sizeof(B) = 48;


### 函數(shù)execve

execve函數(shù)調(diào)用可以執(zhí)行一個(gè)指定的程序,但一旦執(zhí)行了execve函數(shù)之后,調(diào)用execve的進(jìn)程空間就被指定的程序

占據(jù)了.所以execve并不產(chǎn)生新的進(jìn)程,只是將進(jìn)程空間替換而已.

char *ss = {"a","123",NULL};//命令行參數(shù)

execve("a",ss,NULL);


### 函數(shù)wait

父進(jìn)程調(diào)用wait之后會(huì)阻塞,直到子進(jìn)程結(jié)束之后才返回,wait函數(shù)的參數(shù)就是子進(jìn)程的退出碼.

// fork后的父進(jìn)程和子進(jìn)程之間執(zhí)行是隨機(jī)的爆安,無(wú)序的,互相不干擾仔引,因?yàn)樗麄兪莾蓚€(gè)不同的進(jìn)程.

// 變量的地址為偏移地址扔仓,而不是絕對(duì)地址.首地址不一樣,修改變量不會(huì)影響另一個(gè)變量.

// 孤兒進(jìn)程:子進(jìn)程活著,父進(jìn)程死了咖耘,這個(gè)時(shí)候?qū)τ谧舆M(jìn)程來(lái)講父進(jìn)程就變成了init.

// 父進(jìn)程活著翘簇,子進(jìn)程死了,子進(jìn)程就成了僵死進(jìn)程鲤看,等父進(jìn)程收尸缘揪。父進(jìn)程退出的話,僵死的子進(jìn)程也就沒(méi)有了。

// 父進(jìn)程和子進(jìn)程會(huì)共享打開(kāi)的文件描述符.


### 函數(shù)fork

#include

pid_t fork(void);

// fork調(diào)用就是執(zhí)行自己,內(nèi)存中會(huì)出現(xiàn)一模一樣的兩個(gè)進(jìn)程

// fork執(zhí)行成功,向父進(jìn)程返回子進(jìn)程的pid,子進(jìn)程內(nèi)部執(zhí)行fork返回0<若返回0則說(shuō)明代碼運(yùn)行在子進(jìn)程上>

// fork創(chuàng)建的新進(jìn)程是和父進(jìn)程一樣的副本(除了pid不一樣)<變量int m會(huì)被克隆到子進(jìn)程的內(nèi)存空間,變量是兩份>

// 子進(jìn)程沒(méi)有繼承父進(jìn)程的超時(shí)設(shè)置,父進(jìn)程創(chuàng)建的文件鎖.

### 進(jìn)程和線程

進(jìn)程是一個(gè)正在執(zhí)行程序的實(shí)例.// 一個(gè)PID標(biāo)識(shí)一個(gè)進(jìn)程

程序----就是你磁盤(pán)上的那個(gè)文件而已,它是靜態(tài)的.

進(jìn)程----一旦這個(gè)程序備操作系統(tǒng)加載到內(nèi)存,開(kāi)始執(zhí)行了,那么他就是進(jìn)程

// 時(shí)間片模型


# 倒過(guò)來(lái)讀,就很容易理解聲明.

int *pt;//指向int型的指針

const int * pci;//指向const int的指針就是指向整數(shù)常量的指針

int* const p;// 指向int型變量的常量指針,指針地址不可修改.

void (*foo)(int num);//指向參數(shù)為int,返回值為void的函數(shù)的指針,函數(shù)指針

void *foo(int num);//返回值為指針的函數(shù)

int* arr[5];//指針數(shù)組,數(shù)組中每一個(gè)元素都是指針

int (*p)[10] ;// 數(shù)組指針,p指向的是一個(gè)帶10個(gè)int型元素的數(shù)組


### 編程高階

-(int)executeWithCommand:(NSString *)cmd {

NSLog(@"%@",cmd);

NSArray *cmds = [cmd componentsSeparatedByString:@" "];

int argc = (int)cmds.count;

char** argv = (char**)malloc(sizeof(char*)*argc);

for(int i = 0;i < argc; i++) {

? ? ? ?argv[i]=(char*)malloc(sizeof(char)*1024);

? ? ? ?strcpy(argv[i],[[cmds objectAtIndex:i] UTF8String]);

}

int ret = ycmagickmain(argc, argv);

for(int i=0;i < argc;i++){

? ? ? free(argv[i]);

? ? ? free(argv);

? ? ? return ret;

}

### 單鏈表 & 二叉樹(shù)

typedef struct ListElmt_ {

void *data;

struct ListElmt_ *next;

} ListElmt;

typedef struct BiTreeNode_ {

void *data;

struct BiTreeNode_ *left;

struct BiTreeNode_ *right;

} BiTreeNode;

### memset函數(shù)

void *memset(void *s, int ch, size_t n);

函數(shù)解釋?zhuān)簩中當(dāng)前位置后面的n個(gè)字節(jié) (typedef unsigned int size_t )用 ch 替換并返回 s 找筝。

memset:作用是在一段內(nèi)存塊中填充某個(gè)給定的值蹈垢,它是對(duì)較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法

### memcpy函數(shù)

void *memcpy(void *dest, const void *src, size_t n);

從源src所指的內(nèi)存地址的起始位置開(kāi)始拷貝n個(gè)字節(jié)到目標(biāo)dest所指的內(nèi)存地址的起始位置中.

函數(shù)返回指向dest的指針.

### sprintf函數(shù)

功能 把格式化的數(shù)據(jù)寫(xiě)入某個(gè)字符串緩沖區(qū)。

原型 int sprintf( char *buffer, const char *format, [ argument] … );

參數(shù)列表

buffer:char型指針袖裕,指向?qū)⒁獙?xiě)入的字符串的緩沖區(qū)曹抬。

format:格式化字符串。

[argument]...:可選參數(shù)急鳄,可以是任何類(lèi)型的數(shù)據(jù)谤民。

返回寫(xiě)入buffer 的字符數(shù),出錯(cuò)則返回-1. 如果 buffer 或 format 是空指針疾宏,且不出錯(cuò)而繼續(xù)张足,函數(shù)將返回-1,并且 errno 會(huì)被設(shè)置為 EINVAL坎藐。

### 文件操作相關(guān)函數(shù)

函數(shù)原型:FILE * fopen(const char * path,const char * mode);

返回值:文件順利打開(kāi)后为牍,指向該流的文件指針就會(huì)被返回。如果文件打開(kāi)失敗則返回NULL岩馍,并把錯(cuò)誤代碼存在errno中碉咆。

一般而言,打開(kāi)文件后會(huì)做一些文件讀取或?qū)懭氲膭?dòng)作蛀恩,若打開(kāi)文件失敗疫铜,接下來(lái)的讀寫(xiě)動(dòng)作也無(wú)法順利進(jìn)行,所以一般在fopen()后作錯(cuò)誤判斷及處理双谆。

參數(shù)說(shuō)明:

參數(shù)path字符串包含欲打開(kāi)的文件路徑及文件名壳咕,參數(shù)mode字符串則代表著流形態(tài)。

mode有下列幾種形態(tài)字符串:

“r” 以只讀方式打開(kāi)文件佃乘,該文件必須存在囱井。

“r+” 以可讀寫(xiě)方式打開(kāi)文件,該文件必須存在趣避。

”rb+“ 讀寫(xiě)打開(kāi)一個(gè)二進(jìn)制文件,允許讀寫(xiě)數(shù)據(jù)新翎,文件必須存在程帕。

“w” 打開(kāi)只寫(xiě)文件,若文件存在則文件長(zhǎng)度清為0地啰,即該文件內(nèi)容會(huì)消失愁拭。若文件不存在則建立該文件。

“w+” 打開(kāi)可讀寫(xiě)文件亏吝,若文件存在則文件長(zhǎng)度清為零岭埠,即該文件內(nèi)容會(huì)消失。若文件不存在則建立該文件。

“a” 以附加的方式打開(kāi)只寫(xiě)文件惜论。若文件不存在许赃,則會(huì)建立該文件,如果文件存在馆类,寫(xiě)入的數(shù)據(jù)會(huì)被加到文件尾混聊,即文件原先的內(nèi)容會(huì)被保留。(EOF符保留)

”a+“ 以附加方式打開(kāi)可讀寫(xiě)的文件乾巧。若文件不存在句喜,則會(huì)建立該文件,如果文件存在沟于,寫(xiě)入的數(shù)據(jù)會(huì)被加到文件尾后咳胃,即文件原先的內(nèi)容會(huì)被保留。 (原來(lái)的EOF符不保留)

函數(shù)原型:int fclose( FILE *fp );

返回值:如果流成功關(guān)閉旷太,fclose 返回 0展懈,否則返回EOF(-1)。(如果流為NULL泳秀,而且程序可以繼續(xù)執(zhí)行标沪,fclose設(shè)定error number給EINVAL,并返回EOF嗜傅。)

函數(shù)原型 size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;

buffer 用于接收數(shù)據(jù)的內(nèi)存地址

size 要讀的每個(gè)數(shù)據(jù)項(xiàng)的字節(jié)數(shù)金句,單位是字節(jié)

count 要讀count個(gè)數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)size個(gè)字節(jié).

stream 輸入流

返回值

返回真實(shí)寫(xiě)入的項(xiàng)數(shù)吕嘀,若大于count則意味著產(chǎn)生了錯(cuò)誤违寞。另外,產(chǎn)生錯(cuò)誤后偶房,文件位置指示器是無(wú)法確定的趁曼。若其他stream或buffer為空指針,或在unicode模式中寫(xiě)入的字節(jié)數(shù)為奇數(shù)棕洋,此函數(shù)設(shè)置errno為EINVAL以及返回0.

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);

注意:這個(gè)函數(shù)以二進(jìn)制形式對(duì)文件進(jìn)行操作挡闰,不局限于文本文件

返回值:返回實(shí)際寫(xiě)入的數(shù)據(jù)塊數(shù)目

(1)buffer:是一個(gè)指針,對(duì)fwrite來(lái)說(shuō)掰盘,是要獲取數(shù)據(jù)的地址摄悯;

(2)size:要寫(xiě)入內(nèi)容的單字節(jié)數(shù);

(3)count:要進(jìn)行寫(xiě)入size字節(jié)的數(shù)據(jù)項(xiàng)的個(gè)數(shù)愧捕;

(4)stream:目標(biāo)文件指針奢驯;

(5)返回實(shí)際寫(xiě)入的數(shù)據(jù)項(xiàng)個(gè)數(shù)count。

int fseek(FILE *stream, long offset, int fromwhere);函數(shù)設(shè)置文件指針stream的位置次绘。

如果執(zhí)行成功瘪阁,stream將指向以fromwhere為基準(zhǔn)撒遣,偏移offset(指針偏移量)個(gè)字節(jié)的位置,函數(shù)返回0管跺。如果執(zhí)行失敗(比如offset超過(guò)文件自身大小)义黎,則不改變stream指向的位置,函數(shù)返回一個(gè)非0值伙菜。

/* 讀一個(gè)文件,open,close是系統(tǒng)函數(shù),fopen,fclose是庫(kù)函數(shù),建議用庫(kù)函數(shù) */

int fd = open("a.txt",O_RDONLY);

char buf[100] = {0};

while(read(fd,buf,sizeof(buf)-1) > 0)

{

printf("%s",buf);

memset(buf,0,sizeof(buf));

}

// 寫(xiě)文件

write(fd,buf,strlen(buf));

close(fd);//記得關(guān)閉文件

### 數(shù)據(jù)庫(kù)編程

1:)連接到數(shù)據(jù)庫(kù)

MYSQL *mysql_real_connect(MYSQL *pmvsql,const char* hostname,

const char* username,const char* passwd,const char* dbname,0,0,0);

//函數(shù)成功返回指向MySql連接的指針,失敗返回NULL

2:)執(zhí)行SQL語(yǔ)句的函數(shù)

int mysql_query(MYSQL* pmysql,const char* sql);

//成功返回0;

注: 編寫(xiě)mysql程序,連接到server之后,應(yīng)該執(zhí)行sql語(yǔ)句:SET NAMES utf8;

3:)獲取查詢(xún)結(jié)果

MYSQL_RES* mysql_store_result(MYSQL* pmysql);

// 成功返回一個(gè)查詢(xún)結(jié)果指針,查詢(xún)無(wú)結(jié)果或者錯(cuò)誤返回NULL

// 需調(diào)用mysql_free_result(MYSQL_RES *res) 來(lái)釋放相關(guān)資源.

4:)查看查詢(xún)結(jié)果

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

// MYSQL_ROW row相當(dāng)于一個(gè)一行數(shù)據(jù).

// row[0]表示第一列;

### mysql進(jìn)階

1:)查詢(xún)語(yǔ)句

select [ALL|DISTINCT]結(jié)果項(xiàng)列表 from子句 where子句 group子句 having子句 order子句 limit子句

// 上面子句的相對(duì)順序不能打亂,實(shí)際上,在其內(nèi)部計(jì)算的過(guò)程中,也是按此先后順序進(jìn)行的.

// [all | distinct] 顯示全部重復(fù)項(xiàng)(默認(rèn)) 或 消除重復(fù)項(xiàng)

// from 數(shù)據(jù)來(lái)源,表,也可以是表的結(jié)合關(guān)系

// where 條件

// group by 分組

// having 對(duì)分組設(shè)定過(guò)濾條件

// order by 對(duì)前面取得的數(shù)據(jù)來(lái)指定按某個(gè)字段的大小進(jìn)行排序. ASC(正序,默認(rèn)) DESC(倒序)

// 如果指定多個(gè)字段排序,則其含義是,在前一個(gè)字段排序中相同的那些數(shù)據(jù)里,再按后一字段的大小進(jìn)行排序.

// limit [起始行號(hào) start],[要取出的行數(shù) num] --用于分頁(yè)

// 顯示取得第n頁(yè)數(shù)據(jù): select *from t_name limit ($n-1)*$pageSize,$pageSize

2:)數(shù)據(jù)庫(kù)設(shè)計(jì)3范式

第一范式(1NF):原子性轩缤,數(shù)據(jù)不可再分

一個(gè)表中的數(shù)據(jù)(字段值)不可再分

第二范式(2NF):唯一性,消除部分依賴(lài)

一個(gè)表中的每一行必須唯一可區(qū)分贩绕,且非主鍵字段值完全依賴(lài)主鍵字段值

第三范式(3NF):獨(dú)立性火的,消除傳遞依賴(lài)

使一個(gè)表中的任何一個(gè)非主鍵,完全獨(dú)立地依賴(lài)于主鍵淑倾,而不能又依賴(lài)于另外的非主鍵

3:)連接查詢(xún)

基本形式:

from 表1 [連接方式] join 表2 [on 連接條件]馏鹤;連接的結(jié)果可以當(dāng)作一個(gè)“表”來(lái)使用。

交叉連接:

from 表1 [cross] join 表2 娇哆;連接的結(jié)果其實(shí)是兩個(gè)表中的所有數(shù)據(jù)“兩兩對(duì)接”湃累。這種連接也叫做“笛卡爾積”

內(nèi)連接:

from 表1 [inner] join 表2 on 連接條件。inner關(guān)鍵字可以省略碍讨,也可以用cross代替治力。on連接條件無(wú)非是設(shè)定在連接后所得到的數(shù)據(jù)表中,設(shè)定一個(gè)條件以取得所需要的數(shù)據(jù)勃黍。通常連接都是指兩個(gè)有關(guān)聯(lián)的表宵统,則連接條件就是這兩個(gè)表的關(guān)聯(lián)字段的一個(gè)關(guān)系(通常都是相等關(guān)系)

左[外]連接:

from 表1 left [outer] join 表2 on 連接條件;將左邊的表的數(shù)據(jù)跟右邊的表的數(shù)據(jù)以給定的條件連接覆获,并將左邊的表中無(wú)法滿足條件的數(shù)據(jù)(行)也一并取得——即左邊的表的數(shù)據(jù)肯定都取出來(lái)了

右[外]連接:

from 表1 right [outer] join 表2 on 連接條件马澈;將左邊的表的數(shù)據(jù)跟右邊的表的數(shù)據(jù)以給定的條件連接,并將右邊的表中無(wú)法滿足條件的數(shù)據(jù)也一并取得——即右邊的表的數(shù)據(jù)肯定都取出來(lái)了

4:)聯(lián)合查詢(xún)

含義:將兩個(gè)“字段一致”的查詢(xún)語(yǔ)句所查詢(xún)到的結(jié)果以“縱向堆疊”的方式合并到一起弄息,成為一個(gè)新的結(jié)果集痊班。

形式:

select語(yǔ)句1 union [ALL | DISTINCT] select語(yǔ)句2:

說(shuō)明:

兩個(gè)select語(yǔ)句的查詢(xún)結(jié)果的字段需要保持一致:個(gè)數(shù)必須相同,對(duì)應(yīng)順序上的字段類(lèi)型也應(yīng)該相同

ALL | DISTINCT表示兩表的數(shù)據(jù)聯(lián)合后是否需要消除相同行(數(shù)據(jù))摹量。ALL表示不消除(全部取得)涤伐,DISTINCT表示要消除。默認(rèn)不寫(xiě)就會(huì)消除

應(yīng)該將這個(gè)聯(lián)合查詢(xún)的結(jié)果理解為最終也是一個(gè)“表格數(shù)據(jù)”缨称,且默認(rèn)使用第一個(gè)select語(yǔ)句中的字段名

如果第一個(gè)select語(yǔ)句中的列有別名废亭,則order by子句中就必須使用該別名

### TCP通信

1:)套接字使用的步驟

初始化 -> 連接 -> 發(fā)送(接收)數(shù)據(jù) -> 關(guān)閉套接字.

2:)函數(shù)socket()

int socket(int domain,int type,int protocol);

//protocol一般取0,函數(shù)返回值是成功返回套接字描述符,

//失敗返回-1,domain一般取AF_INET,

//type: SOCK_STREAM使用TCP,SOCK_DGRAM使用UDP不可靠連接.

外部依賴(lài): #include

#include

3:)函數(shù)bind()

int bind(int sockfd,const struct sockaddr *my_addr,socklen_t addrlen);

// bind將進(jìn)程與一個(gè)套接字聯(lián)系起來(lái),通常用于服務(wù)器進(jìn)程為接入客戶連接建立一個(gè)套接口;

// sockfd是socket函數(shù)調(diào)用返回的套接口值,

// my_addr是結(jié)構(gòu)sockaddr的地址

// addrlen設(shè)置了my_addr能容納的最大字節(jié)數(shù).

4:)函數(shù)listen()

int listen(int sockfd,int backlog)

// 服務(wù)端調(diào)用該函數(shù)來(lái)監(jiān)聽(tīng)指定端口的客戶端連接

// sockfd還是socket標(biāo)示符

// backlog 最大并發(fā)數(shù)

5:)函數(shù)accept()

int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

// 當(dāng)有客戶端連接到服務(wù)端,它們會(huì)排入隊(duì)列,直到服務(wù)端準(zhǔn)備好處理他們?yōu)橹?

// accept會(huì)返回一個(gè)新的套接口,同時(shí)原來(lái)的套接口繼續(xù)listen.

// accept會(huì)阻塞,直到有客戶端連接.

6:)函數(shù)connect()

int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);

// 客戶端調(diào)用connect與服務(wù)端進(jìn)行連接.

// $0表示的是客戶端的socket.

7:)函數(shù)send() --發(fā)送數(shù)據(jù)

ssize_t send(int s,const void* buf,size_t len,int flags);

// s是已經(jīng)建立連接的套接口

// buf是要發(fā)送數(shù)據(jù)內(nèi)存buffer

// len指明buffer的大小

// flags取0.

// 成功,返回發(fā)送的字節(jié)數(shù),

函數(shù)recv與send類(lèi)似:

ssize_t recv(int s,void *buf,size_t len,int flags);

最后,記得要調(diào)用close(int sockfd)來(lái)關(guān)閉socket;

### epoll函數(shù)使用舉例

struct epoll_event ev,events[100];//數(shù)組用于回傳要處理的事件

int epfd = epoll_create(100);//可以放100個(gè)socket

ev.data.fd = listen_st;//設(shè)置與要處理的事件相關(guān)的文件描述符

ev.events = EPOLLIN | EPOLLERR | EPOLLHUP(掛起);//設(shè)置要處理的事件類(lèi)型

epol_ctl(epfd,EPOLL_CTL_ADD,listen_st,&ev);//注冊(cè)epoll事件

int nfds = epoll_wait(epfd,events,100,-1);//等待epoll事件的發(fā)生

### 共享庫(kù)so

// so文件在linux為共享庫(kù)

// 編譯時(shí)gcc需要加-fPIC,使gcc產(chǎn)生與位置無(wú)關(guān)的代碼[具體函數(shù)入口位置由主調(diào)進(jìn)程處理]

// 鏈接時(shí)gcc使用-shared選項(xiàng),指示生成一個(gè).so文件

// 庫(kù)文件格式為lib*.so

// 提供一個(gè)與該共享庫(kù)配套的頭文件[聲明so文件中的函數(shù)]

// .bash_profile 中添加 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

// 使得程序鏈接時(shí)會(huì)在當(dāng)前目錄下尋找so文件

// gcc -L. -ltest -o hello hello.o [-L.表示在當(dāng)前目錄尋找so文件,-ltest表示鏈接libtest.so]

// 在.h文件中增加__cplusplus的預(yù)編譯指令,就可被C++調(diào)用這個(gè)庫(kù)了

### so文件配套的頭文件舉例

#ifndef TEST_H_

#define TEST_H_

#ifdef __cpluscplus

extern "C"

{

#endif

int max(int a,int b);

int add(int a,int b);

#ifdef __cplusplus

}

#endif

#endif

### 有名管道FIFO

$ mkfifo fifo1? ? # 創(chuàng)建有名管道fifo1

// 有名管道具有持久性

// 有名管道可在任意兩個(gè)進(jìn)程間通信

### 信號(hào)

1:)信號(hào)通常用來(lái)向一個(gè)進(jìn)程通知事件

信號(hào)是不可提前預(yù)知的,所以信號(hào)是異步的.

比如硬件異常,非法內(nèi)存引用,在鍵盤(pán)上按一個(gè)鍵等都會(huì)發(fā)出信號(hào).

ctrl+c --> 發(fā)出SIGINT信號(hào)

2:)通過(guò)fork函數(shù)產(chǎn)生的進(jìn)程與父進(jìn)程處理信號(hào)一樣.

捕捉信號(hào):signal函數(shù)

3:)守護(hù)進(jìn)程的創(chuàng)建

- 父進(jìn)程中執(zhí)行fork后,執(zhí)行exit退出

- 在子進(jìn)程中調(diào)用setsid.

- 讓根目錄/ 成為子進(jìn)程的工作目錄[會(huì)調(diào)用chdir函數(shù)]

- 把子進(jìn)程的umask設(shè)為0 [ umask(0) ]

- 關(guān)閉任何不需要的文件描述符

//與守護(hù)進(jìn)程通信,則需要向守護(hù)進(jìn)程發(fā)信號(hào)

### Shell腳本

1:)shell腳本舉例

#!/bin/sh

WHOAMI='whoami'

PID= `ps -u $WHOAMI | grep signd | awd '{print $1}'`

if (test "$PID" = "") then

./signd

fi

2:)

### man命令的使用

// atoi函數(shù)需要引入什么頭文件,不用去死記, $man atoi 查看一下就知道了

// 比如gcc命令的使用 ,$man gcc

### 棋盤(pán)坐標(biāo)的計(jì)算

* 棋盤(pán)坐標(biāo)的計(jì)算首先要搞清楚棋盤(pán)坐標(biāo)原點(diǎn)在屏幕坐標(biāo)系中的坐標(biāo)是多少,

* 再一個(gè)需要弄清楚棋盤(pán)上落點(diǎn)之間的間隔是多少;最終計(jì)算出每個(gè)棋子的屏幕坐標(biāo);

* 棋子的坐標(biāo) = 棋子在棋盤(pán)的單位坐標(biāo)*棋子的直徑+棋盤(pán)坐標(biāo)系相對(duì)于屏幕坐標(biāo)系的偏移量.

* 因?yàn)樵诒斫Y(jié)構(gòu)中紅棋的id始終在前邊,所以不管紅棋在下邊還是黑棋在下邊,都是先擺紅棋,再擺黑棋.

### 判斷是否點(diǎn)擊了某個(gè)象棋

void Scene::ccTouchEnded(CCTouch *pTouch,CCEvent *e)

{

CCPoint ptClickUp = pTouch->getLocation();//獲取手指離開(kāi)屏幕的瞬時(shí)坐標(biāo)

if(_red->boundingBox().containsPoint(ptClickUp)){

//表示精靈被點(diǎn)擊

this->_redSprClicked = true;

}

}

### 象棋的碰撞檢測(cè)

scheduleUpdate();//啟動(dòng)定時(shí)器,會(huì)每一幀調(diào)用update方法

void udpate(float delta){

//精靈默認(rèn)的錨點(diǎn)是在它的中心

//一般情況下,是判斷兩個(gè)精靈的矩形是否有相交的部分,因?yàn)檫@里有旋轉(zhuǎn),所以不能用這個(gè).

//象棋是圓形,只需判斷兩個(gè)圓的圓心距是否小于r1+r2

float x1 = m_sp1->getPositionX();

float x2 = m_sp2->getPositionY();

if(abs(x1-x2)getContentSize().width*0.5

//兩個(gè)精靈發(fā)生碰撞

//開(kāi)始游戲,進(jìn)入主場(chǎng)景

CCDirector::sharedDirector->replaceScene(SceneGame::scene());

}

}

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

/* 函數(shù) */

### memset函數(shù)

原型:extern void *memset(void *buffer, char c, int count);

用法:#include

功能:把buffer所指內(nèi)存區(qū)域的前count個(gè)字節(jié)設(shè)置成字符c。

說(shuō)明:返回指向buffer的指針

### strcpy函數(shù)實(shí)現(xiàn)

char *strcpy(char *strDest, const char *strSrc)

{

assert((strDest!=NULL) && (strSrc !=NULL)); // 2分

char *address = strDest; // 2分

while( (*strDest++ = * strSrc++) != ‘\0’ ) // 2分

NULL ;

return address ; // 2分

}

### inet_addr函數(shù)

/* Convert Internet host address from numbers-and-dots notation in CP

into binary data in network byte order.? */

extern in_addr_t inet_addr (const char *__cp) __THROW;

eg: inet_addr("192.168.1.23");

### setsockopt函數(shù)

int setsockopt(int s,int level,int optname,const void* optval,socklen_t optlen);

// 設(shè)置套接口,SO_REUSEADDR指示系統(tǒng)地址可重用.

int on = 1;

setsockopt(st,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

### read函數(shù)

read(STDIN_FILENO,s,sizeof(s));//從鍵盤(pán)讀取字符串,并緩存到s中

write(STDOUT_FILENO,buf,strlen(buf));//向控制臺(tái)寫(xiě)數(shù)據(jù)

### fcntl函數(shù)

int fcntl(int fd,int cmd,.../* arg */);

//該函數(shù)可以將文件或socket描述符設(shè)置為阻塞或非阻塞狀態(tài)

//fd是要設(shè)置的文件描述符或socket

//cmd F_GETFL為得到目前狀態(tài),F_SETFL為設(shè)置狀態(tài)

//宏定義0_NOBLOCK表示非阻塞,0代表阻塞

//返回值為描述符當(dāng)前狀態(tài)

### epoll_*函數(shù)

epoll相當(dāng)于一個(gè)游泳池.

epoll_create() --用來(lái)創(chuàng)建一個(gè)epoll文件描述符;需要調(diào)用close()來(lái)關(guān)閉epoll句柄.

epoll_ctl() --用來(lái)修改需要偵聽(tīng)的文件描述符或事件;

epoll_wait() --接收發(fā)生在被偵聽(tīng)的描述符上的,用戶感興趣的IO事件;

int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);

// epfd是epoll_create的返回值

// op EPOLL_CTL_ADD:注冊(cè)新的fd到epfd中

// fd是socket描述符

// event 通知內(nèi)核需要監(jiān)聽(tīng)什么事件

int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout);

// epfd是epoll_create的返回值

// epoll_events里面將存儲(chǔ)所有的讀寫(xiě)事件

// maxevents是當(dāng)前需要監(jiān)聽(tīng)的所有socket句柄數(shù)

// timeout -1表示一直等下去

### fork函數(shù)

#include

pid_t fork(void);//進(jìn)程克隆

fork執(zhí)行成功,向父進(jìn)程返回子進(jìn)程的pid,并向子進(jìn)程返回0,函數(shù)返回0表示的是子進(jìn)程;

fork創(chuàng)建的新進(jìn)程是和父進(jìn)程一樣的副本.(除了PID和PPID);

提示: 獲取pid的方法 --> getpid(),getppid()

### execve函數(shù)

int execve(const char* path,const char *arg,char * const envp[]);

fork創(chuàng)建了一個(gè)新的進(jìn)程,產(chǎn)生一個(gè)新的PID;

execve用被執(zhí)行的程序完全替換了調(diào)用進(jìn)程的映像;

execve啟動(dòng)一個(gè)新程序,替換原有進(jìn)程,所以被執(zhí)行的進(jìn)程pid不變;

path? --? 要執(zhí)行的文件完整路徑

arg? ? --? 傳遞給程序完整參數(shù)列表

envp? --? 指向執(zhí)行execed程序的環(huán)境指針,可以設(shè)為NULL

### getcwd函數(shù)

char* getcwd(char* buf,size_t size);

該函數(shù)把當(dāng)前工作目錄的絕對(duì)路徑名復(fù)制到buf中,size指示buf的大小.

### opendir函數(shù)

DIR *opendir(const char* pathname);//打開(kāi)pathname指向的目錄文件

struct dirent *readdir(DIR *dir);//讀出目錄文件內(nèi)容

int closedir(DIR *dir);

### getlogin函數(shù)

getlogin()函數(shù)返回程序的用戶名;

struct passwd* getpwnam(const char* name);//返回/etc/passwd文件中與該登錄名相應(yīng)的一行完整信息

### system函數(shù)

int system(const char* cmd);

//該函數(shù)傳遞給/bin/.sh/cmd中可以包含選項(xiàng)和參數(shù)

//如果沒(méi)有找到/bin/sh 函數(shù)返回127,

### wait函數(shù)

pid_t wait(int *status);//阻塞調(diào)用,直到子進(jìn)程退出,wait才返回

pid_t waitpid(pid_t pid,int *status,int options);

// wait和waitpid函數(shù)收集子進(jìn)程的退出狀態(tài)

// status保存子進(jìn)程的退出狀態(tài)

// pid為等待進(jìn)程的pid

// 父進(jìn)程沒(méi)有調(diào)用wait函數(shù),子進(jìn)程就退出了,這個(gè)時(shí)候子進(jìn)程就成了僵死進(jìn)程

### exit函數(shù)

int exit(int status);

// 導(dǎo)致進(jìn)程正常終止,并且返回給父進(jìn)程的狀態(tài)

// 無(wú)論進(jìn)程為何終止,最后都執(zhí)行相同的代碼,關(guān)閉文件,釋放內(nèi)存資源

// void abort()函數(shù)會(huì)導(dǎo)致程序異常終止

### kill函數(shù)

int kill(pid_t pid,int sig);

// kill函數(shù)殺死一個(gè)進(jìn)程,由pid指定

// sig表示信號(hào)

### pipe函數(shù)

int pipe(int filedes[2]);

// 如果成功建立了管道,則會(huì)打開(kāi)兩個(gè)文件描述符,一個(gè)用于讀數(shù)據(jù),一個(gè)用于寫(xiě)數(shù)據(jù)

// 關(guān)閉管道用close函數(shù)

### mkfifo函數(shù)

int mkfifo(const char* pathname,mode_t mode);

// 創(chuàng)建fifo,函數(shù)執(zhí)行成功返回0

// pathname代表fifo的名稱(chēng)

// mode表示讀寫(xiě)權(quán)限,比如777

// unlink(const char*) 函數(shù)刪除fifo

### shmget函數(shù)

int shmget(key_t key,size_t size,int shm_flg);

// 創(chuàng)建共享內(nèi)存區(qū)

// 參數(shù)key既可以是IPC_PRIVATE,也可以是ftok函數(shù)返回的一個(gè)關(guān)鍵字

// size指定段的大小,shm_flg表示權(quán)限0xxx

// 函數(shù)成功則返回段標(biāo)示符

// 兩個(gè)進(jìn)程要共享一塊內(nèi)存,實(shí)際上是一塊內(nèi)存分別映射到兩個(gè)進(jìn)程,由操作系統(tǒng)對(duì)這塊內(nèi)存進(jìn)行同步

// $ipcs -m #查看共享內(nèi)存

### shmat函數(shù)

void* shmat(int shmid,const void* shmaddr,int shmflg);

// 附加共享內(nèi)存區(qū)

// shmid為要附加的共享內(nèi)存區(qū)標(biāo)示符

// shmaddr一般置為0,由系統(tǒng)分配地址

// shmflg可以是SHM_RDONLY只讀

// 函數(shù)成功則返回被附加了段的地址

// 函數(shù)shmdt(const void* shmaddr)是將附加在shmaddr的段從調(diào)用進(jìn)程的地址空間分離出去

### signal函數(shù)

signal(int signo,void (*func))

// signo 信號(hào)名

// func? 回調(diào)函數(shù)的名稱(chēng)

int sigaction(int signo,const struct sigaction *act,struct sigaction *oact)

該函數(shù)是signal的升級(jí)版,會(huì)檢查或修改與指定信號(hào)相關(guān)聯(lián)的處理動(dòng)作

### raise函數(shù)

int raise(int signo);

// 發(fā)送信號(hào),raise函數(shù)一般用于進(jìn)程向自身發(fā)送信號(hào).

unsigned int alarm(unsigned int seconds);

// 設(shè)置定時(shí)器,當(dāng)時(shí)間到了則發(fā)出SIGALARM信號(hào)

### sleep函數(shù)

unsigned int sleep(unsigned int seconds);

// seconds指定睡眠時(shí)間

// 到時(shí)間后函數(shù)返回.

### openlog函數(shù)

void openlog(const char* ident,int option,int facility);//打開(kāi)日志

void syslog(int priority,const char* format,...);//寫(xiě)入日志

void closelog();//關(guān)閉日志

### pthread_create函數(shù)

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,

void* (*start_routine)(void*),void *arg)

// 線程創(chuàng)建函數(shù),[在進(jìn)程中只有一個(gè)控制線程,主線程return,整個(gè)進(jìn)程就終止]

// thread是新線程的ID,

// attr_t 線程屬性

// start_routine回調(diào)函數(shù)

// arg是線程啟動(dòng)的附加參數(shù)

// 函數(shù)成功則返回0

// gcc鏈接時(shí)要加-lpthread

注: 多個(gè)線程創(chuàng)建后線程的運(yùn)行順序具有隨機(jī)性;

### pthread_exit函數(shù)

void pthread_exit(void* arg);

// 單個(gè)線程退出函數(shù)

// 任一線程調(diào)用exit函數(shù),整個(gè)進(jìn)程就會(huì)終止

// arg會(huì)被其他線程調(diào)用,比如pthread_join捕捉

// 線程中不要用信號(hào)來(lái)處理邏輯,這樣會(huì)使得程序變得很復(fù)雜

### pthread_join函數(shù)

int pthread_join(pthread_t th,void** thr_return);

// 該函數(shù)用于掛起當(dāng)前線程,直至th指定的線程終止才返回

// 如果另一個(gè)線程返回值不為空則保存在thr_return中

### pthread_detach函數(shù)

int pthread_detach(pthread_t th);

// 使線程處于被分離狀態(tài)

// 對(duì)于被分離狀態(tài)的線程,調(diào)用pthread_join無(wú)效

// 如果不等待一個(gè)線程,同時(shí)對(duì)該線程的返回值不感興趣,可以設(shè)置為該線程為被分離狀態(tài)

// 自己不能使自己成為分離狀態(tài),只能由其他線程調(diào)用pthread_detach

### pthread_cancel函數(shù)

// pthread_cancel函數(shù)允許一個(gè)線程取消th指定的另一個(gè)線程

// 函數(shù)成功則返回0

// pthread_equal函數(shù)判斷兩個(gè)線程是否是同一個(gè)線程

### pthread_attr_init函數(shù)

int pthread_attr_init(pthread_attr_t *attr);

// pthread_attr_init函數(shù)初始化attr結(jié)構(gòu)[線程屬性]

// pthread_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);#線程創(chuàng)建時(shí)則為被分離狀態(tài)

// pthread_attr_destroy函數(shù)釋放attr內(nèi)存空間

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末具钥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子液兽,更是在濱河造成了極大的恐慌骂删,老刑警劉巖掌动,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宁玫,居然都是意外死亡粗恢,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)欧瘪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)眷射,“玉大人,你說(shuō)我怎么就攤上這事佛掖⊙铮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵芥被,是天一觀的道長(zhǎng)欧宜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拴魄,這世上最難降的妖魔是什么冗茸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮匹中,結(jié)果婚禮上夏漱,老公的妹妹穿的比我還像新娘。我一直安慰自己顶捷,他們只是感情好挂绰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著焊切,像睡著了一般扮授。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上专肪,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天刹勃,我揣著相機(jī)與錄音,去河邊找鬼嚎尤。 笑死荔仁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的芽死。 我是一名探鬼主播乏梁,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼关贵!你這毒婦竟也來(lái)了遇骑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤揖曾,失蹤者是張志新(化名)和其女友劉穎落萎,沒(méi)想到半個(gè)月后亥啦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡练链,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年翔脱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒鼓。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡届吁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绿鸣,到底是詐尸還是另有隱情疚沐,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布枚驻,位于F島的核電站濒旦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏再登。R本人自食惡果不足惜尔邓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锉矢。 院中可真熱鬧梯嗽,春花似錦、人聲如沸沽损。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绵估。三九已至炎疆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間国裳,已是汗流浹背形入。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缝左,地道東北人亿遂。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渺杉,于是被迫代替她去往敵國(guó)和親蛇数。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容