c/c++/gcc

gdb

生成core文件的條件
     -g       // gcc -g main.c -o exe
    ulimit -c 1024    // ulimit -a
    權限問題:exe文件的擁有者,否則可能不能生成core文件。  // 用root, 不用sudo。sudo沒有打印“core dumped"
core文件的相關信息
    默認位置:同exe文件的位置,若程序中有chdir(),則有可能改變。
    默認名字:core
    可以通過 /proc/sys/kernel/core*,等配置文件修改    // echo 1 > core_uses_pid
查看相應的exe文件:
     file coreFile    
    gdb -c coreFile    
    readelf -h coreFile
利用core分析程序問題:
     gdb -c coreFile exeFile  
    gdb exeFile coreFile     
        backtrace,   bt  2(打印2層棧)
gdb的使用
     開啓:gdb exeFile    
    給exe文件傳入參數:set args/run  -t 5 -i data/rtp.data
    查看代碼:set/show listsize,     list +/-,  list 151,  list  funcName,  list  45, 49
         (gdb) list wiucs::RecordConvert::convert
    打斷點:break 151;  b  filename:151;   b  WebmMuxer::open;   
         break  199  if x == 2(x若是局部變量,則需要到此代碼處,再打斷點)
         watch x > 2(x處理同上,x>2的值若有改變,則斷點產生)
    斷點管理:delete 4(斷點號),   disable/enable 4,   clear 151(代碼行號),   tbreak 151
    查看變量:print  varName;  display/undisplay  varName(遇斷點時,自動顯示); 
         whatis mediaHead(查看結構體);  
         set print pretty on
        (gdb) p ntohs(seqnum) 
    控制流程:run,  next,  step(into func), finish(outof func),   continue/until 159, 
    改流程:return 111,    jump 159(直接跳到159行),   signal 11(發段錯誤信息使程序停止執行)
    設置值:set variable var_p = (char *)malloc(2)   or  print var_p = ...
    線程:thread 3(切換到線程3);
         break 88 thread 3 if x == y     // 當線程3執行到88行並且變量x和y值相等時中斷
    查看信息:where,   frame 9(進入9號幀),  up / down-silently(上下移動幀),    
         info locals/args/threads/frame/line(當前幀下的信息)
        (gdb) info all-registers  寄存器中放置了程序運行時的數據,比如程序當前運行的指令地址(ip),程序的當前堆棧地址(sp)
          (gdb) disassemble func   // 打印出彙編代碼
gdb問題:
    有斷點停不下來  // 實際停下來了,只是按continue時,沒有返回,又按了一次,導致C兩次,斷點打印在前面 

gcc 尋找頭文件

1. 當前文件夾;    2. -I ;    3. /usr/include    4. gcc的環境變量C_INCLUDE_PATH...
#include <系統路徑>          // 查找順序 3, 4, 1, 2     
#include “對此C文件的路徑”    // 查找順序 1,2,3,4  

生成靜態庫  

1.  gcc -c a.c  // 編譯成.o
// ar命令中不能加-lXXX, ar: two different operation options specified
2.  ar -rcs  libXXX.a  obj1.o  obj2.o    (ar=archive, r=replace, c=create, s=)

生成動態庫 

gcc -fPIC -shared -o libxxx.so a.c b.c
    gcc -fPIC -o a.o -c a.c      // gcc -c a.c
    gcc -shared -o libxxx.so a.o // gcc -fPIC -shared -o libXXX.so a.o

查看庫中的內容

ar tv libXXX.a   // 查看靜態庫含有的.o文件
nm -s libXXX.a   // 查看靜態動態庫中的.o以及函數: U引用  T定義  W弱態
ldd libXXX.so    // 查看so中的引用的so

庫的使用

1. -L;  2. LD_LIBRARY_PATH;  3. /etc/ld.so.conf ---> ldconfig ---> ld.so.cache;  4. /lib, /usr/lib
靜態庫:編譯時尋找的順序:1,2,3,4;  編譯完成後.a的代碼集成在exe中,執行時無需.a文件了。
動態庫:編譯時尋找的順序同上; 執行時仍然需要.so,其查找順序爲: -Wl,-rpath,/path1/:/path2(無空格,冒號),2,3,4

Q&A

0. LD_LIBRARY_PATH已經包含了動態庫所需要的路徑,但是程序還是找不到所需要的庫
    場景1:LD_LIBRARY_PATH=...:A:...:B:...  
         A,B路徑都包含libjvm.so, libjava.so , 但是B=$JAVA_HOME/jre/lib/amd64/
   結果:程序只在A中找所有需要的jre庫
      Error occurred during initialization of VM
     Unable to load native library: /opt/wiucs-cvt/libjava.so: cannot open shared object file: 
       No such file or director	
   解決方法:  A,B位置互換;  或者刪除A中的.so

   場景2:export LD_LIBRARY_PATH=/tmp;   
          當前shell調用 httpd, httpd 的子進程執行CGI程序,CGI程序需要新的SO 
   結果:儘管/tmp下有所需要的動態庫,但是CGI仍然引用不到
   解決方法:export後僅當前shell(控制檯)及其子shell(httpd)可用,CGI是httpd的子進程所以引用不到; 
        指定執行動態庫時的搜索路徑: 
        mips2_fp_le-gcc -o getPageInfo -Wl,-rpath,/tmp $(OBJS) $(LIBS)   
1. 多個-l的順序:根據依賴關係,反序排列! 
    g++ -o test IsacDecoder.cpp... -I... -L... -liSAC -lCNG -lsignal_processing -lpthread
2. 找不到庫中函數:nfs: server is working? // 動態庫在nfs server上
3. 程序既要和libhello進行靜態連接,又要和libbye進行動態連接,
    其命令應爲: gcc testlib.o -o exefile -WI,-Bstatic -lhello -WI,-Bdynamic -lbye 
   -static -lXXX // 強制使用靜態庫(同時存在,默認動態庫優先)  
4. 動態庫的應用:做插件 plugin  // dlopen, dlsym

gcc 命令

gcc -o hello hello.c  -save-temps(一步,保留中間文件)
預處理        gcc -o hello.i  -E hello.c
編譯和彙編    gcc -o hello.o  -c hello.i  // ccl and as
鏈接          gcc -o hello hello.o  // ld  
生成依賴關係  gcc -MM a.c     // a.o: a.c; -MMD: 生成.d .o 
-Dmacro  
  相當於C語言中的#define macro      
-Dmacro=defn  
  相當於C語言中的#define macro=defn  
調試打印 #gcc -DDLD_DEBUG -O0 -g3 -Wall -c 
#ifdef DLD_DEBUG
#define dbprintf(fmtstr, args...)  \
		{printf(fmtstr, ##args); printf("\n");}
#else
#define dbprintf(fmtstr, args...)
#endif	

基本

0. 工具:Enterprise architecture 
1. 可執行文件的執行時間 time ./test
2. 一般的系統都把內核源碼放在/usr/src下面
3. #include <math.h> -lm 一定要加上 
4. could not read symbols: Malformed archive libCNG.a 移動位置後 失效 ?
5. case UE_KEY_SK01 ... UE_KEY_SK06:  ??
6. static: C中表示本地文件,不能被異地引用  &&  多次重入函數時引用上次保存的值
    類中static 的數據,需要在外部進行初始化,因爲只能有一份。 singleObj* singleObj::_Obj = NULL;
7. yasm是彙編編譯器:爲了提高效率用到了彙編指令的程序需要yasm
8. 結構體中的指定初始化  
 struct {
  char exten[AST_MAX_EXTENSION];
  char context[AST_MAX_CONTEXT];
 } pickup = {
   .exten = "",
 };
9. ptrdiff_t: 兩個指針相減的結果,long int, stddef.h(cstddef)
10. 把不同命令空間裏的類作爲友類:在各自類的頭文件中,對另一個類進行前向聲明。
        不需要包含對方的頭文件(聲明瞭可編譯,鏈接時從動態庫以及頭文件中去找?)。
    如:SessionRecord 的友類是 ConvertToWebm,這樣後者就可以訪問前者的私有成員。
    SessionRecord.h:  // the same with COnvertTowebm.h
        namespace erizo{
            class ConvertToWebm;
        }
        namespace wiucs{
            friend class erizo::ConvertToWebm;
            class SessionRecord{
            }
        }
11. list.assign(3, 7);  // 3重複7次賦值
     list.assign(listA.begin, listA.end)  // 範圍賦值
12. 類之間的關係:
      關聯association: A中有B的引用或變量,固定性
      泛化generalization: 繼承
      依賴dependency: 局部變量,方法參數,偶然臨時性
      聚合agregation: 個體與羣體
      組合composite: 部件與整體
13. 編譯64位: 不一定在64位機器上編譯; 編譯參數加上 -m64 ; 
       需要安裝完整版gcc, sudo apt-get install gcc-multilib
14. join() // 主線程等待分支線程結束: branch_thread_.join()
       注意控制使得有循環的分支線程可以結束掉

常用函數以及處理

日誌:
    c/C++: log4cxx,這個是Apache的開源,強烈建議C++用戶使用,跨平臺,支持多線程等優勢;
    這個容易導致程序崩潰:log4Cplus 
open VS fopen
    open: 系統調用,返回文件描述符;設備文件只能用open
	saveFd = open("/tmp/CLI_traceRoute.log", O_RDWR | O_CREAT | O_TRUNC, 0766);
	write...
	lseek(saveFd, 0, SEEK_SET);
	ret = read(saveFd, buf, MAXBUF);		
	close(saveFd); 
          open/close, read/write, getc/putc, getchar/putchar 等。       
    fopen:標準庫函數(調用open),返回FILE指針;可移植;用緩存實現
	FILE *fp = fopen("/proc/net/route", "r");
	while (fgets(buf, sizeof(buf), fp))
	fclose(fp);
          fopen/fclose/freopen, fread/fwrite, fgetc/fputc, fgets/fputs, fseek/ftell/rewind等
          寫文件後再用rewind()不起作用 // 關閉後,重新打開
比較:
    輸出: fprintf (file或者描述符) vs sprintf(stringBuf),snprintf,vsnprintf(可變長的buf)  
           printf("ID:%x", this); // 打印對象; 後面加fflush(stdout);可提高打印效率
   輸入: fscan (read from file)  
網絡字節序轉換
     uint16_t curSeq = ntohs(rh->seqnum);
    uint32_t curTs = ntohl(rh->timestamp);
修改打印字符串的顏色
    // "\033[0;34m" = blue    "\033[0m" = none
    snprintf(buf, size, "\033[0;34m[%d/%02d/%02d %02d:%02d:%02d] %s\033[0m",
       1900+tm->tm_year, 1+tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, content);
opendir // 目錄下的目錄流
    readdir // 目錄的特性
        stat(fullName, &dstat)
       S_ISDIR(dstat.st_mode)
       closedir(dir);		
    if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) //#include <io h=""> 
    chdir(url + 1) != 0  // change cur process work path  //unistd.h
    if(realpath(purl + 1, realpath_buff) != NULL) // 由相對路徑得到絕對路徑
包裹函數,安全的函數
    snprintf(緩存地址,長度,格式,參數1...)  
    fgets(gets) strncpy(strcpy) strncat(strcat)
各種字串之間的轉換
    其他類型(String, Qstring, Cstring)先轉換爲基本類型char*, 然後再轉換  
    string - char* 
        string str1(str2); // const char* str2 = "char";
	char* str2 = const_cast<char>(str1.c_str());// string str1 ="string";		
    QString - char*
	QString qstr(QString::fromLocal8Bit(str)); // const char* str = "string."; 
	const char* str2 = qstr.toLocal8Bit();
    QString - string
		QString s2q(const string &s)  
		{  
    			return QString(QString::fromLocal8Bit(s.c_str()));  
		}  
		string q2s(const QString &s)  
		{  
    			return string((const char *)s.toLocal8Bit());  
		}  					
    CString - char* 
	char *ch = cstr.GetBuffer(cstr.GetLength() + 1); // CString cstr = "cstring.";
	    cstr.ReleaseBuffer();		 
系統執行
    system(buf); // sprintf(buf,"/etc/network.rc LOAD&");
設置非阻塞
    fcntl(sockfd ,F_SETFL, O_NONBLOCK); 
信號以及鬧鈴
    sigaction(SIGALRM, &sa, NULL);   //他是POSIX的信號接口,而signal()是標準C的信號接口
    alarm(TIMEOUT) >= 0 // 經過指定秒數後,給當前進程發送 SIGALRM 信號;後一個鬧鐘將會取消前一個,並從0開始計時,返回前個鬧鐘剩餘的秒數。
shutdown(a_c_w, SHUT_WR);  //這樣關閉套接字更安全比其他方式	
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
    是作用於數據拷貝在兩個文件描述符之間的操作函數.這個拷貝操作是內核中操作的,所以稱爲"零拷貝".//#include <sys h="" sendfile="">
    sendfile函數比起read和write函數高效得多,因爲read和write是要把數據拷貝到用戶應用層操作.	
url = alloca(strlen(buf) + 12);   // alloca 是在棧上分配空間的,儘量不要用。

strtok VS strtok_r 
	分別使用兩個 strtok ,會互相干擾(函數中的靜態指針,指向下個字串的)
	pStr = strtok_r(buf, "\n", &outer_ptr);
sscanf會從buffer裏讀進數據,依照argument的設定將數據寫回。 
	sscanf與scanf類似,都是用於輸入的,只是後者以鍵盤(stdin)爲輸入源,前者以固定字符串爲輸入源。 
	count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank);  	
         從輸入buf以及各式,生成所需字串 sscanf(data,"username=%[^&]&password=%[^&]",username,password);		
#include <string.h>
	char *strerror(int errnum);
	int strerror_r(int errnum, char *buf, size_t n);
		說明,對於函數strerror_r,第一個參數errnum是錯誤代碼,第二個參數buf是用戶提供的存儲錯誤描述的緩存,第三個參數n是緩存的大小。
數組
	char array[10];
	&array = array  // 其值相等,不表示賦值
	But, (&array + 1) != (array + 1)  
	// 數組名是數組第一個元素的地址,常量不可改變。所以
	char * p = NULL;   // &p爲指針變量存放的地址。&array 常量無需存放的地址,表示整個數組的地址
	func(char ** p);   // func(&array);  是錯誤的,其值等於array, 並沒有取得二級地址。
指針的指針: 
        指針的初始值爲NULL,把指針的地址記住,分配一段空間後,把分配的空間的地址通過剛纔的記住的指針的地址寫到指針的值中 指
針與引用的比較
         int *p; VS int a; int &v = a; //引用必初始化
         int *p = &a; VS 引用不能修改	
函數返回char *
	如果返回的是棧:野指針,因爲函數返回時棧被回收,亂指一氣
	堆:誰釋放
	全局:擴大作用域
	在函數中定義靜態數組: static char value[64];   //如果不是多線程重入,static 也是不錯的選擇
網絡通信中的數據傳輸——————————採用外部表示法
	網絡層中:數據以二進制表示
	異構機: 指硬件不同,數據表示也不同
	如
	A:大端 32位  VS  B:小端 16位  // 整數表示
	C: ASCII     VS  B:  unicode   // 字符表示
	外部表示法: SUN XDR ---> ASN.1  --> XML	
高位低位的轉換寫法:
	低位字  翻到高位字
	低位字節翻到高位字節
	比如1030 0f00 寫爲高位低位:
		    低位字  翻到高位字  -》0f00  1030, 
		然後低位字節翻到高位字節-》000f: 3010,完成。
			然後寫成20位地址模式:高位字左移12位,得到 f000:3010
字串轉化爲長整形	
	char buffer[20]="10379cend$3";
	char *stop;
	printf("%d\n",strtol(buffer, &stop, 2));  //stop返回非法字符的首地址; 2爲轉換的2進制
	printf("%s\n", stop);
	輸出結果:2,	379cend$3
16進制的數字40轉換爲10進制串
	char message[3];
	sprintf(message, "%d", 40); //字串40
	// 將字串40按照16進制來轉化,得到10進制數字
	long int prelen = strtol(message, NULL, 16);
         sprintf(message, "%ld", prelen);  // print str "64"
字串轉double	
	strtod  > Convert string to double 
	atoi   > Convert string to int 
	atol > Convert string to long int 
字串複製
	t = strdup(s);  // 函數內分配內存
	free(t);   // don't forget!	
字串比較,忽略大小寫	
	strcasecmp	
在源字串中查找目的字串中任一字符,並返回第一個找時的地址。		
	urlp = strpbrk(iobuf, " \t");
	result = strpbrk( string, "0123456789" );//在string中找出最先出現0~9中某一個字符的位置
字串中查找字符	
	tptr = strchrnul(urlp, ' ');      // 未找到,返回串尾
	script = strchr(script + 1, '/')  // 未找到,返回NULL	
	char * p = strrchr(buf, ' ');     // 反向搜索字符	
小寫字符變大寫	
	0100 0001 65        41          A
	0110 0001 97        61          a
	ch = (buf[0] & ~0x20); /* toupper if it's a letter */
C 正則表達式函數
	#include <regex h="">	
	regcomp(結構體指針, 正則表達式,標誌);
	regexec(編譯好的結構體, 待查找的字串,找到的個數,找到的結構體數組,標誌);
打印N個相同的字符,且字符數字爲變量	
	fprintf(stderr, "%*c ^\n", iLen, ' ');		
</regex></sys></char></io>

C++文件包含C的函數

 #ifdef __cplusplus
 extern "C" {
 #endif
    ...
    ...
    ...
 #ifdef __cplusplus
 }
 #endif

C文件包含C++的函數

1. 將c文件需要的c++函數提取出來,放到另一個單獨的c++文件中,
2. 並在該文件及其頭文件都加extern "C"
3. 然後在c文件中include 其頭文件即可

頭文件

 #ifndef __INCfooLibh
 #define __INCfooLibh
   #include
    #define
 const int  // 常量定義塊
 typedef struct    //複合類型定義塊
 void func(void);  //函數原型說明塊
 #endif /* __INCfooLibh */

數組內元素的個數

#define ARRAY_SIZE(x)   ( (unsigned) ( sizeof(x) / sizeof((x)[0]) ) ) 
// x should be arrayName, not pointer to Array!!!!!!!!
 int a = sizeof(p) ;      // 指針的長度爲4
 int b = sizeof((p)[0]);  // 元素的長度可能爲8
 所以 numofData = ARRAY_SIZE(p);  //0.   

定義數組個數

 1、#define   LISTEN_NUM   10   
 2、const int LISTEN_NUM = 10;   
UserProfile users[LISTEN_NUM];
     若用2的方式,運行時才確定,所以用gcc編譯會出現Error: variably modified 'users' at file scope
     改成1的形式,則沒有報錯信息。編譯時確定。

連接符##和#轉字符串 

// 因爲是C語言宏定義的,所以只在編譯時起作用,運行時不行
#define A(x) T_##x        //字串連接: A(1)------〉T_1
#define B(x)   #@x        //加單引號: B(1)------〉'1'
#define C(x)    #x        //加雙引號: C(1)------〉"1"
例子1: #define paster(n) printf( "token" #n "  = %d\n", token##n )
       那麼paster(9)在編譯時,上面的這句話被擴展爲: printf( "token"  "9"  " = %d", token9 );  
例子2: #define CLI_RINGTONE_LINE(i)  <a>RINGTONE_LINE##i
</a>       #define _GETSTR(test) #test
       #define  GETSTR(test) _GETSTR(test)
          printf("%s", GETSTR(CLI_RINGTONE_LINE(2)));  // 內外的宏都展開,則 output is “<a>RINGTONE_LINE2“
       #define</a> GETSTR(test)  #test    // 如果沒有中間層的宏,則 output is ”CLI_RINGTONE_LINE(2)“

可變參數 

// 用可變參數宏(variadic macros)傳遞可變參數表
#define dgbmsg(fmt,...)  printf(fmt,__VA_ARGS__) // #define debug(...)  printf(__VA_ARGS__)
// GCC 宏前面加上##的作用在於,當可變參數的個數爲0時,這裏的##起到把前面多餘的","去掉的作用,否則會編譯出錯
#define dbgprint(format,args...)  fprintf(stderr, format, ##args)
   1) __VA_ARGS__  只有gcc支持,C++不支持。 // #include <stdarg h="">   
    2) __FILE__     宏在預編譯時會替換成當前的源文件名
  3) __LINE__     宏在預編譯時會替換成當前的行號
  4) __FUNCTION__ 宏在預編譯時會替換成當前的函數名稱
1. 變參的實現
#include <stdarg.h> 
wiCallCtrlSyslog(const char *_format, ...)
{
    va_list ap;  // 分配存放變參的內存 char*
    va_start(ap, _format); // 初始化,確定變參開始位置
    rc = vsnprintf(fmt_buf, 255, _format, ap); // vsnprintf函數:格式化字符串複製 
    va_end(ap);
    printf("[Call Ctrl] %s", fmt_buf);
}
2. 例子:  
有時,我們想把調試信息輸出到屏幕上,而有時則又想把它輸出到一個文件中,可參考下面的例子:
//debug.c
#include <stdio h="">
#include <string h="">
//開啓下面的宏表示程序運行在調試版本, 否則爲發行版本, 這裏假設只有調試版本才輸出調試信息
#define _DEBUG
#ifdef _DEBUG
    //開啓下面的宏就把調試信息輸出到文件,註釋即輸出到終端
    #define DEBUG_TO_FILE
    #ifdef DEBUG_TO_FILE
        //調試信息輸出到以下文件
        #define DEBUG_FILE "/tmp/debugmsg"
        //調試信息的緩衝長度
        #define DEBUG_BUFFER_MAX 4096
        //將調試信息輸出到文件中
        #define printDebugMsg(moduleName, format, ...) {\
            char buffer[DEBUG_BUFFER_MAX+1]={0};\
            snprintf( buffer, DEBUG_BUFFER_MAX \
                    , "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );\
       		FILE* fd = fopen(DEBUG_FILE, "a");\
            if ( fd != NULL ) {\
                fwrite( buffer, strlen(buffer), 1, fd );\
                fflush( fd );\
                fclose( fd );\
            }\
        }
    #else
        //將調試信息輸出到終端
        #define printDebugMsg(moduleName, format, ...) \
                  printf( "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
    #endif //end for #ifdef DEBUG_TO_FILE
#else
    //發行版本,什麼也不做
    #define printDebugMsg(moduleName, format, ...)
#endif //end for #ifdef _DEBUG
int main(int argc, char** argv)
{
    int data = 999;
    printDebugMsg( "TestProgram", "data = %d", data );
    return 0;
}
</string></stdio></stdarg>

守護進程

單獨的守護進程:httpd
 /etc/init.d
超級守護進程:多了個一個管理員xinet,並且調用下面的進程時,分爲多線程,單線程形式
 /etc/xinet.d
#include <unistd.h>
int daemon(int nochdir, int noclose); //成功返回0,失敗返回-1
    daemon()函數,主要用於某些程序希望自己脫離終端的控制而運行於後臺的情況。
       除非nochdir爲非零值,如果nochdir爲0,那麼daemon會從當前目錄,更改到根目錄(“/”)下運行。   // chdir
      除非noclose爲非零值,如果noclose爲0,那麼daemon會將標準輸入,標準輸出,標準錯誤輸出重定向到/dev/null。 // dup2
    父進程自殺,讓子進程成爲孤兒進程。
	子進程創建新的會話,併成爲該會話的頭領進程  // setsid      

開發問題

1. buf[10]設置過小,實際可能寫入了12個數據,從而導致程序掛掉(退出函數時纔出錯,可能退出時在回收資源時掛掉)
2. 初始化時,正確設置初始值;用完後及時清空問題,確保下次正確執行
3. 多線程對共享資源進行搶佔,加鎖確保共享資源不被破壞。一個線程寫,一個線程讀,也要加鎖;讀操作,其本質可能會對資源進行寫操作。
4. main() 放在namespace裏面,就報錯:無定義。
5. QT4安裝所需的庫
   sudo apt-get install libx11-dev libfreetype6-dev libavahi-gobject-dev libSM-dev libXrender-dev libfontconfig-dev libXext-dev<p>
6. 安裝指定版本的glibc
   ./busybox: /lib/libc.so.6: version `GLIBC_2.7' not found (required by ./busybox)
   檢查當前的版本: ll /lib/libc.so.6 
   下載: wget http://ftp.gnu.org/pub/gnu/glibc/glibc-2.12.1.tar.gz
   配置 # ./glibc-2.12.1/configure --prefix=/usr/local/glibc2.12.1/ --with-headers=/usr/include
   編譯 # cd glibc-2.7 ; make ; make install 
7. 在ubuntu中LD_LIBRARY_PATH不起作用。據說因爲安全原因,Linux系統做了限制。
8. 注意不同命名空間中,攜帶空間的名字: erizo::ConvertToWebm 中 wiucs::SessionRecord,  
9. 注意 #ifndef XXX_H_,有可能這裏的名字寫錯,造成寫了頭文件但沒有被引用到
10. ConvertToWebm c 要消費,SessionRecord s 中生產的 std::list<queue> audio_list_
       錯誤:c. list = s.list // 僅僅是賦值操作,後續s.list中的變化,不能反映到c.list中
       正確:c 中包含s指針,c實際處理的是s的數據: this->ps->list
</queue></p>

CLI

CLIisWorking
	ps |grep debugsh |grep -v grep > /tmp/clips.txt
ignoreOutput
	g_saveFd = dup(1);
	g_newFd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0766);
	dup2(g_newFd, 1)	
password
	getchar() and save in the passwd[]
	termios.h  tcgetattr()  and   err = tcsetattr(fd, TCSAFLUSH, &term);  // del or add ECHOFLAGS		
array	
	char tmpbuf[MAXPARAMS][MAXPARAMNAME] = { {0} };	
	strcpy(tmpbuf[argc], temp); // temp is string			
command tree
typedef struct cmd{
 char *name;/*命令名稱*/
 STUHELP help;
 struct cmd *subCmd;/*子命令集指針*/
 funcHandleCmd handleCmd;/*命令執行函數*/
 EnCmdMode Auth;
} CMD;	
CMD rootCMD[] = {
		{"aec",
				{"Acoustic Echo Cancellation commands\n",
				 "channelid [dev deviceid] {enable | disable | status}"},
				&nullCMD, Aec, all_mode
		},
};		
	pSubCommand = lookforSubCmd(pCmdName, pNodeCMD, &retChkCmd);   // 檢查命令
		if (NULL == pSubCommand)  // 沒有這個命令 或者 找到兩個
		else if (&nullCMD == pSubCommand) // 找完了OK
		else	//繼續找下一級	
	retChkArg = checkCmdArg(syntaxStr, startIndex, endIndex, argv, &cmdParams); //檢查參數	
		retChkGrp = checkGroup(startGrp, &endGrp, &argType, tmpArgStr);     //loop {} [] XX
		retFill = fillBraketParam(tmpArgStr, ¶mNo, pParams, argc, &index, argv);   // [{} XXX {} YYY]
			or retFill = fillParam(¶mNo, pParams, argType, tmpArgStr, argc, &index, argv);


readline
	initialize_readline ();
		rl_bind_key('?', cmd_help);
			s = rl_copy_text(0, rl_point);  // hostname> show ?  s = show 得到提示字串後的輸入
			return main();  	//Solution the problem that using the "?" and "Tab" can not bind the Enter key
		rl_bind_key('\t',cmd_tab_completer);
			s = rl_copy_text(0, rl_point);		//get input
			_rl_replace_text(line, len, rl_point);
			rl_insert_text(" ");	
	// while(1)
	line = readline(prompt); 
	add_history(str);	
	execCmd(str);
	free(line);	
recursive readdir
	void getLsStr(char *path, char *lsStr) call itself when stat tells it's S_ISDIR  // my first
something about CLI
	getopt, readline, lex and yacc, flex and bison

線程鎖

一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數相關)
一次只能一個線程擁有互斥鎖,其他線程只有等待
LINUX多線程互斥量和讀寫鎖區別
    boost庫中提供了mutex類與lock類,通過組合可以輕易的構建讀寫鎖與互斥鎖。
    mutex類主要有兩種:
         獨佔互斥類:  boost::mutex, 有lock和unlock方法,
         共享互斥類:  boost::shared_mutex, lock/unlock,還有shared_lock/shared_unlock。
    lock類
	獨佔鎖(寫鎖):  boost::unique_lock<t>, T爲任意mutex
	共享鎖(讀鎖):  boost::shared_lock<t>中的T只能是shared_mutex類
	upgrade_lock,它的最大特點就是與shared_lcok不互斥,與別的upgrade_lock和unique_lock互斥。
	upgrade_lock可以升級爲upgrade_to_unique_lock。據boost文檔說也可以downgrade成shared_lock
   boost:mutex:soped_lock  // 定義範圍內加鎖有效
注意:
    鎖時ABC的連環扣,解鎖需要按照這個順序
    對隊列等的讀操作,實際有寫得動作,比如修改下標,所以還是要用寫鎖
    從共享的數據,以及參與的線程,來制定鎖的方案。
</t></t>

算法

    排序算法
    穩定性:數值相同的兩個數,經過排序後,他們之間的相對位置保持不變,稱爲穩定排序。
    內/外排序:待排序的數字都在內存,爲內排序;如果部分在內存,排序後調整外存上的數據,爲外排序。
    時間/空間複雜度:計算複雜程度,存儲空間
       選擇排序:選擇最小的放在第一個,剩下的選擇最小放第二個位置...
         堆排序:建立堆(二叉樹),堆頂爲最大元素;堆頂與最後一個元素交換,建立堆...
      插入排序:一個一個插入到前面有序的數列中
          希爾排序:按照增量劃分組,組內插入排序,直到增量爲1
       冒泡排序:相鄰兩個數比較排序,每輪最大的數沉底
          快速排序:一趟掃描,按照基準元素排序,左邊的數<基準<右邊...

算法

 CASE軟件(Computer Aided Software Engineering)。  在需求分析階段,系統分析與設計階段,系統開發及部署等方面有着強大的支持  交互圖(interaction),協作圖(communication)和時序圖(Timing),  狀態圖(State),部署圖(Deployment),組件圖(component),活動圖(Activity),

boost

 
#include <boost hpp="" asio="">  
    boost::asio::io_service &_ioservice
    boost::asio::ip::udp::socket* _socket 
        = new udp::socket(_ioservice, udp::endpoint(udp::v4(), port)); 
    boost::asio::ip::udp::endpoint to_point(
        boost::asio::ip::address::from_string(ip), port);
    發送端:socket.send_to(發送到哪裏endpoint==ip,port)
    //async_receive_from異步接收,不阻塞; receive_from沒有收到數據時,不能返回
    接收端:_socket(用誰接收==port)->async_receive_from()
#include <boost hpp="" mutex="" thread="">
    boost::mutex _socketMutex;
    _socketMutex.lock();
    _socketMutex.unlock();
#include <boost hpp="" array="">
    boost::array<char buf_size=""> _recv_buf;
    boost::asio::buffer(_recv_buf)  
#include <boost hpp="" bind="">
    boost::bind(&boost::asio::io_service::run, &_ioservice)
#include <boost hpp="" thread="">
    boost::thread _thread;
    _thread = boost::thread(&ForwardSender::send, this);
</boost></boost></char></boost></boost></boost>
<boost hpp="" asio=""><boost hpp="" mutex="" thread=""><boost hpp="" array=""><char buf_size=""><boost hpp="" bind=""><boost hpp="" thread="">
</boost></boost></char></boost></boost></boost>
<boost hpp="" asio=""><boost hpp="" mutex="" thread=""><boost hpp="" array=""><char buf_size=""><boost hpp="" bind=""><boost hpp="" thread="">

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章