c/c++/gcc

来源:互联网 发布:专业手机数据恢复 编辑:程序博客网 时间:2024/05/17 20:28

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 specified2.  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 -lpthread2. 找不到库中函数: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 ./test2. 一般的系统都把内核源码放在/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是汇编编译器:为了提高效率用到了汇编指令的程序需要yasm8. 结构体中的指定初始化   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-multilib14. join() // 主线程等待分支线程结束: branch_thread_.join()       注意控制使得有循环的分支线程可以结束掉

常用函数以及处理

日志:    c/C++: log4cxx,这个是Apache的开源,强烈建议C++用户使用,跨平台,支持多线程等优势;    这个容易导致程序崩溃:log4Cplus open VS fopen    open: 系统调用,返回文件描述符;设备文件只能用opensaveFd = 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 - stringQString 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$316进制的数字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"字串转doublestrtod  > 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, '/')  // 未找到,返回NULLchar * p = strrchr(buf, ' ');     // 反向搜索字符小写字符变大写0100 0001 65        41          A0110 0001 97        61          ach = (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 _DEBUGint 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

CLIisWorkingps |grep debugsh |grep -v grep > /tmp/clips.txtignoreOutputg_saveFd = dup(1);g_newFd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0766);dup2(g_newFd, 1)passwordgetchar() and save in the passwd[]termios.h  tcgetattr()  and   err = tcsetattr(fd, TCSAFLUSH, &term);  // del or add ECHOFLAGSarraychar tmpbuf[MAXPARAMS][MAXPARAMNAME] = { {0} };strcpy(tmpbuf[argc], temp); // temp is stringcommand treetypedef 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) // 找完了OKelse//继续找下一级retChkArg = checkCmdArg(syntaxStr, startIndex, endIndex, argv, &cmdParams); //检查参数retChkGrp = checkGroup(startGrp, &endGrp, &argType, tmpArgStr);     //loop {} [] XXretFill = fillBraketParam(tmpArgStr, ¶mNo, pParams, argc, &index, argv);   // [{} XXX {} YYY]or retFill = fillParam(¶mNo, pParams, argType, tmpArgStr, argc, &index, argv);readlineinitialize_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 keyrl_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 readdirvoid getLsStr(char *path, char *lsStr) call itself when stat tells it's S_ISDIR  // my firstsomething about CLIgetopt, 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="">
	
				
		
原创粉丝点击