欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Mjpeg-streamer源碼分析(一)
  Mjpeg-streamer源碼分析
     
--------------------------------------------------------------------------------------------------
基礎知識:
 條件變量:
  條件變量是利用線(xiàn)程間共享的全局變量進(jìn)行同步的一種機制,主要包括兩個(gè)動(dòng)作:
  一個(gè)線(xiàn)程等待"條件變量的條件成立"而掛起;另一個(gè)線(xiàn)程使"條件成立"(給出條件成立信號)。
  為了防止競爭,條件變量的使用總是和一個(gè)互斥鎖結合在一起。
  
  當程序進(jìn)入pthread_cond_wait等待后,將會(huì )把g_mutex進(jìn)行解鎖,
  當離開(kāi)pthread_cond_wait之前,g_mutex會(huì )重新加鎖。所以在main中的g_mutex會(huì )被加鎖。
  
 動(dòng)態(tài)鏈接庫的操作函數:
  #include <dlfcn.h>
  void *dlopen(const char *filename, int flag); /* 打開(kāi)動(dòng)態(tài)鏈接庫,返回動(dòng)態(tài)庫句柄handle */
  char *dlerror(void);    /* 返回由于dlopen(),dlsym()或者dlclose()產(chǎn)生的錯誤 */
  void *dlsym(void *handle, const char *symbol); /* 通過(guò)handle,獲得動(dòng)態(tài)庫內函數的地址,之后通過(guò)該地址調用動(dòng)態(tài)庫內的函數 */
  int dlclose(void *handle);   /* 關(guān)閉動(dòng)態(tài)庫 */
  Link with -ldl.     /* 注意,程序在編譯的時(shí)候要用-ldl */
  
 字符串操作函數:
  #include <string.h>
  char *strchr(const char *s, int c);  /* 返回字符串s第一次出現c的指針 */
  char *strrchr(const char *s, int c);  /* 返回字符串s最后一次出現c的指針 */
  char *strdup(const char *s);   /* 復制字符串s,返回指向新字符串的指針(malloc\free) */
  char *strndup(const char *s, size_t n);  /* 復制字符串s最多n個(gè)字符,如果s正好有n個(gè),'\0'將自動(dòng)被添加 */
  char *strdupa(const char *s);   /* 調用alloca函數在站內分配內存 */
  char *strndupa(const char *s, size_t n); /* 調用alloca函數在站內分配內存 */


  
 守護進(jìn)程:
  守護進(jìn)程最重要的特性是后臺運行;其次,守護進(jìn)程必須與其運行前的環(huán)境隔離開(kāi)來(lái)。
  這些環(huán)境包括未關(guān)閉的文件描述符,控制終端,會(huì )話(huà)和進(jìn)程組,工作目錄以及文件創(chuàng )建掩模等。
  這些環(huán)境通常是守護進(jìn)程從執行它的父進(jìn)程(特別是shell)中繼承下來(lái)的;
  最后,守護進(jìn)程的啟動(dòng)方式有其特殊之處------它可以在 Linux系統啟動(dòng)時(shí)從啟動(dòng)腳本/etc/rc.d中啟動(dòng),
  可以由作業(yè)規劃進(jìn)程crond啟動(dòng),還可以由用戶(hù)終端(通常是shell)執行。
  總之,除開(kāi)這些特殊性以外,守護進(jìn)程與普通進(jìn)程基本上沒(méi)有什么區別,
  因此,編寫(xiě)守護進(jìn)程實(shí)際上是把一個(gè)普通進(jìn)程按照上述的守護進(jìn)程的特性改造成為守護進(jìn)程。
  
 守護進(jìn)程的編程要點(diǎn)
  1. 在后臺運行。
  為避免掛起控制終端將Daemon放入后臺執行。方法是在進(jìn)程中調用fork使
  父進(jìn)程終止, 讓Daemon在子進(jìn)程中后臺執行。
  if(pid=fork()) exit(0); //是父進(jìn)程,結束父進(jìn)程,子進(jìn)程繼續
  2. 脫離控制終端,登錄會(huì )話(huà)和進(jìn)程組
  有必要先介紹一下Linux中的進(jìn)程與控制終端,登錄會(huì )話(huà)和進(jìn)程組之間的關(guān)系:
  進(jìn)程屬于 一個(gè)進(jìn)程組,進(jìn)程組號(GID)就是進(jìn)程組長(cháng)的進(jìn)程號(PID)。
  登錄會(huì )話(huà)可以包含多個(gè)進(jìn)程組。這些進(jìn)程組共享一個(gè)控制終端。這個(gè)控制終端通常是創(chuàng )建進(jìn)程的登錄終端。
  控制終端,登錄會(huì )話(huà)和進(jìn)程組通常是從父進(jìn)程繼承下來(lái)的。我們的目的就是要擺脫它們 ,使之不受它們的影響。
  方法是在第1點(diǎn)的基礎上,調用setsid()使進(jìn)程成為會(huì )話(huà)組長(cháng):
  setsid();
  說(shuō)明:當進(jìn)程是會(huì )話(huà)組長(cháng)時(shí)setsid()調用失敗。但第一點(diǎn)已經(jīng)保證進(jìn)程不是會(huì )話(huà)組長(cháng)。
  setsid()調用成功后,進(jìn)程成為新的會(huì )話(huà)組長(cháng)和新的進(jìn)程組長(cháng),并與原來(lái)的登錄會(huì )話(huà)和進(jìn)程組脫離。
  由于會(huì )話(huà)過(guò)程對控制終端的獨占性,進(jìn)程同時(shí)與控制終端脫離。
  3. 禁止進(jìn)程重新打開(kāi)控制終端
  現在,進(jìn)程已經(jīng)成為無(wú)終端的會(huì )話(huà)組長(cháng)。但它可以重新申請打開(kāi)一個(gè)控制終端。
  可以通過(guò)使進(jìn)程不再成為會(huì )話(huà)組長(cháng)來(lái)禁止進(jìn)程重新打開(kāi)控制終端:
  if(pid=fork()) exit(0); //結束第一子進(jìn)程,第二子進(jìn)程繼續(第二子進(jìn)程不再是會(huì )話(huà)組長(cháng))
  4. 關(guān)閉打開(kāi)的文件描述符
  進(jìn)程從創(chuàng )建它的父進(jìn)程那里繼承了打開(kāi)的文件描述符。
  如不關(guān)閉,將會(huì )浪費系統資源, 造成進(jìn)程所在的文件系統無(wú)法卸下以及引起無(wú)法預料的錯誤。
  按如下方法關(guān)閉它們:
  for(i=0;i 關(guān)閉打開(kāi)的文件描述符close(i);
  5. 改變當前工作目錄
  進(jìn)程活動(dòng)時(shí),其工作目錄所在的文件系統不能卸下。一般需要將工作目錄
  改變到根目錄 。對于需要轉儲核心,寫(xiě)運行日志的進(jìn)程將工作目錄改變到特定目錄如/tmp
  chdir("/")
  6. 重設文件創(chuàng )建掩模
  進(jìn)程從創(chuàng )建它的父進(jìn)程那里繼承了文件創(chuàng )建掩模。它可能修改守護進(jìn)程所創(chuàng )建的文件的存取位。
  為防止這一點(diǎn),將文件創(chuàng )建掩模清除:
  umask(0);
  7. 處理SIGCHLD信號
  處理SIGCHLD信號并不是必須的。但對于某些進(jìn)程,特別是服務(wù)器進(jìn)程往往在請求到來(lái)時(shí)生成子進(jìn)程處理請求。
  如果父進(jìn)程不等待子進(jìn)程結束,子進(jìn)程將成為僵尸進(jìn)程(zombie )從而占用系統資源。
  如果父進(jìn)程等待子進(jìn)程結束,將增加父進(jìn)程的負擔,影響服務(wù)器 進(jìn)程的并發(fā)性能。
  在Linux下可以簡(jiǎn)單地將SIGCHLD信號的操作設為SIG_IGN。
  signal(SIGCHLD,SIG_IGN);
  這樣,內核在子進(jìn)程結束時(shí)不會(huì )產(chǎn)生僵尸進(jìn)程。
  這一點(diǎn)與BSD4不同,BSD4下必須顯式等待子進(jìn)程結束才能釋放僵尸進(jìn)程.
  
   關(guān)于/dev/null及用途
    把/dev/null看作"黑洞". 它非常等價(jià)于一個(gè)只寫(xiě)文件.
    所有寫(xiě)入它的內容都會(huì )永遠丟失. 而嘗試從它那兒讀取內容則什么也讀不到.
    然而, /dev/null對命令行和腳本都非常的有用.
    禁止標準輸出.
  1 cat $filename >/dev/null
     2 # 文件內容丟失,而不會(huì )輸出到標準輸出.
  禁止標準錯誤
  1 rm $badname 2>/dev/null
     2 # 這樣錯誤信息[標準錯誤]就被丟到太平洋去了.
  禁止標準輸出和標準錯誤的輸出.
  1 cat $filename 2>/dev/null >/dev/null
     2 # 如果"$filename"不存在,將不會(huì )有任何錯誤信息提示.
     3 # 如果"$filename"存在, 文件的內容不會(huì )打印到標準輸出.
     4 # 因此Therefore, 上面的代碼根本不會(huì )輸出任何信息.
     5 # 當只想測試命令的退出碼而不想有任何輸出時(shí)非常有用。
     6 #-----------測試命令的退出 begin ----------------------#
     7 # ls dddd 2>/dev/null 8
     8 # echo $?    //輸出命令退出代碼:0為命令正常執行,1-255為有出錯。 
     9 #-----------測試命令的退出 end-----------# 
     10# cat $filename &>/dev/null
     11 #也可以, 由 Baris Cicek 指出.
  清除日志文件內容
  1 cat /dev/null > /var/log/messages
     2 #  : > /var/log/messages   有同樣的效果, 但不會(huì )產(chǎn)生新的進(jìn)程.(因為:是內建的)
     3
     4 cat /dev/null > /var/log/wtmp
  例子 28-1. 隱藏cookie而不再使用
  1 if [ -f ~/.netscape/cookies ]  # 如果存在則刪除.
     2 then
     3   rm -f ~/.netscape/cookies
     4 fi
     5
     6 ln -s /dev/null ~/.netscape/cookies
     7 # 現在所有的cookies都會(huì )丟入黑洞而不會(huì )保存在磁盤(pán)上了.
    
--------------------------------------------------------------------------------------------------
首先,分析該軟件的結構體:
--------------------------------------------------------------------------------------------------
globals結構體:
--------------------------------------------------------------------------------------------------
 typedef struct _globals globals; /* mjpg-streamer只支持一個(gè)輸入插件,多個(gè)輸出插件 */
 struct _globals {
   int stop;    /* 一個(gè)全局標志位 */
   pthread_mutex_t db;   /* 互斥鎖,數據鎖 */
   pthread_cond_t  db_update;  /* 條件變量,數據更新的標志 */
   unsigned char *buf;   /* 全局JPG幀的緩沖區的指針 */
   int size;    /* 緩沖區的大小 */
   input in;    /* 輸入插件,一個(gè)輸入插件可對應多個(gè)輸出插件 */
   output out[MAX_OUTPUT_PLUGINS];  /* 輸出插件,以數組形式表示 */
   int outcnt;    /* 輸出插件的數目 */
 };
--------------------------------------------------------------------------------------------------
input結構體:
 /* structure to store variables/functions for input plugin */
 typedef struct _input input;
 struct _input {
   char *plugin;    /* 動(dòng)態(tài)鏈接庫的名字,或者是動(dòng)態(tài)鏈接庫的地址 */
   void *handle;    /* 動(dòng)態(tài)鏈接庫的句柄,通過(guò)該句柄可以調用動(dòng)態(tài)庫中的函數 */
   input_parameter param;  /* 插件的參數 */
   int (*init)(input_parameter *); /* 四個(gè)函數指針 */
   int (*stop)(void);
   int (*run)(void);
   int (*cmd)(in_cmd_type, int);  /* 處理命令的函數 */
 };
 
/* parameters for input plugin */
 typedef struct _input_parameter input_parameter;
 struct _input_parameter {
   char *parameter_string;
   struct _globals *global;
 };
-------------------------------------------------------------------------------------------------- 
output結構體:
 /* structure to store variables/functions for output plugin */
 typedef struct _output output;
 struct _output {
   char *plugin;    /* 插件的名字 */
   void *handle;    /* 動(dòng)態(tài)鏈接庫的句柄,通過(guò)該句柄可以調用動(dòng)態(tài)庫中的函數 */
   output_parameter param;  /* 插件的參數 */
   int (*init)(output_parameter *); /* 四個(gè)函數指針 */
   int (*stop)(int);
   int (*run)(int);
   int (*cmd)(int, out_cmd_type, int); /* 處理命令的函數 */
 };

/* parameters for output plugin */
 typedef struct _output_parameter output_parameter;
 struct _output_parameter {
   int id;    /* 用于標記是哪一個(gè)輸出插件的參數 */
   char *parameter_string;
   struct _globals *global;
 };
--------------------------------------------------------------------------------------------------
現在開(kāi)始分析main()函數:
--------------------------------------------------------------------------------------------------
默認情況下,程序會(huì )將video0作為輸入,http的8080端口作為輸出  (fps = frames per second)
 char *input  = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";
 char *output[MAX_OUTPUT_PLUGINS];  /* 一個(gè)輸入最大可以對應10個(gè)輸出 */
 output[0] = "output_http.so --port 8080"; /* 將video0作為輸入,http的8080端口作為輸出 */
-------------------------------------------------------------------------------------------------- 
下面是一個(gè)while()循環(huán),來(lái)解析main()函數后面所帶的參數
 /* parameter parsing */
 while(1) {
 int option_index = 0, c=0;
 static struct option long_options[] = \ /* 長(cháng)選項表,進(jìn)行長(cháng)選項的比對 */
 {
  {"h", no_argument, 0, 0},  /* 第一個(gè)參數為選項名,前面沒(méi)有短橫線(xiàn)。譬如"help"、"verbose"之類(lèi) */
  {"help", no_argument, 0, 0},  /* 第二個(gè)參數描述了選項是否有選項參數 |no_argument 0 選項沒(méi)有參數|required_argument 1 選項需要參數|optional_argument 2 選項參數可選|*/
  {"i", required_argument, 0, 0},  /* 第三個(gè)參數指明長(cháng)選項如何返回,如果flag為NULL,則getopt_long返回val。
  {"input", required_argument, 0, 0},  * 否則返回0,flag指向一個(gè)值為val的變量。如果該長(cháng)選項沒(méi)有發(fā)現,flag保持不變.
  {"o", required_argument, 0, 0},   */
  {"output", required_argument, 0, 0}, /* 第四個(gè)參數是發(fā)現了長(cháng)選項時(shí)的返回值,或者flag不是NULL時(shí)載入*flag中的值 */
  {"v", no_argument, 0, 0},
  {"version", no_argument, 0, 0},
  {"b", no_argument, 0, 0},  /* 每個(gè)長(cháng)選項在長(cháng)選項表中都有一個(gè)單獨條目,該條目里需要填入正確的數值。數組中最后的元素的值應該全是0。
  {"background", no_argument, 0, 0},  *數組不需要排序,getopt_long()會(huì )進(jìn)行線(xiàn)性搜索。但是,根據長(cháng)名字來(lái)排序會(huì )使程序員讀起來(lái)更容易. 
  {0, 0, 0, 0}     */     
 };
--------------------------------------------------------------------------------------------------
 c = getopt_long_only(argc, argv, "", long_options, &option_index);
--------------------------------------------------------------------------------------------------
下面重點(diǎn)分析一下getopt_long_only函數:
 int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
 該函數每解析完一個(gè)選項,就返回該選項字符。
 如果選項帶參數,參數保存在optarg中。如果選項帶可選參數,而實(shí)際無(wú)參數時(shí),optarg為NULL。
 當遇到一個(gè)不在optstring指明的選項時(shí),返回字符'?'。如果在optstring指明某選項帶參數而實(shí)際沒(méi)有參數時(shí),返回字符'?'或者字符':',視optstring的第一個(gè)字符而定。這兩種情況選項的實(shí)際值被保存在optopt中。
 當解析錯誤時(shí),如果opterr為1則自動(dòng)打印一條錯誤消息(默認),否則不打印。
 當解析完成時(shí),返回-1。
 每當解析完一個(gè)argv,optind就會(huì )遞增。如果遇到無(wú)選項參數,getopt默認會(huì )把該參數調后一位,接著(zhù)解析下一個(gè)參數。如果解析完成后還有無(wú)選項的參數,則optind指示的是第一個(gè)無(wú)選項參數在argv中的索引。
 最后一個(gè)參數longindex在函數返回時(shí)指向被搜索到的選項在longopts數組中的下標。longindex可以為NULL,表明不需要返回這個(gè)值
-------------------------------------------------------------------------------------------------- 
 /* no more options to parse */
 if (c == -1) break;
 /* unrecognized option */
 if(c=='?'){ help(argv[0]); return 0; }
 switch (option_index) {
 /* h, help */
 case 0:
 case 1:
 help(argv[0]);
 return 0;
 break;
 /* i, input */
 case 2:
 case 3:
 input = strdup(optarg);
 break;
 /* o, output */
 case 4:
 case 5:
 output[global.outcnt++] = strdup(optarg);
 break;
 /* v, version */
 case 6:
 case 7:
 printf("MJPG Streamer Version: %s\n" \
 "Compilation Date.....: %s\n" \
 "Compilation Time.....: %s\n", SOURCE_VERSION, __DATE__, __TIME__);
 return 0;
 break;
 /* b, background */
 case 8:
 case 9:
 daemon=1;
 break;
 default:
 help(argv[0]);
 return 0;
 }
 }
--------------------------------------------------------------------------------------------------
好,現在分析一下該程序是否需要成為守護進(jìn)程:
  /* fork to the background */
  if ( daemon ) {     /* 當命令后面設置了b命令時(shí),daemon就會(huì )被置為1 */
   LOG("enabling daemon mode");
   daemon_mode(); 
  }
 現在看一看daemon_mode()時(shí)如何創(chuàng )建守護進(jìn)程的
   void daemon_mode(void) {
     int fr=0;
     fr = fork();
     if( fr < 0 ) {   /* fork失敗  */
       fprintf(stderr, "fork() failed\n");
       exit(1);
     }
     if ( fr > 0 ) {   /* 結束父進(jìn)程,子進(jìn)程繼續  */
       exit(0);
     }
     if( setsid() < 0 ) {   /* 創(chuàng )建新的會(huì )話(huà)組,子進(jìn)程成為組長(cháng),并與控制終端分離 */
       fprintf(stderr, "setsid() failed\n");
       exit(1);
     }
     fr = fork();    /* 防止子進(jìn)程(組長(cháng))獲取控制終端 */
     if( fr < 0 ) {   /* fork錯誤,退出 */
       fprintf(stderr, "fork() failed\n");
       exit(1);
     }
     if ( fr > 0 ) {   /* 父進(jìn)程,退出 */
       fprintf(stderr, "forked to background (%d)\n", fr);
       exit(0);
     }     /* 第二子進(jìn)程繼續執行 , 第二子進(jìn)程不再是會(huì )會(huì )話(huà)組組長(cháng)*/
     umask(0);    /* 重設文件創(chuàng )建掩碼 */
     chdir("/");    /* 切換工作目錄 */
     close(0);    /* 關(guān)閉打開(kāi)的文件描述符*/
     close(1);
     close(2);
     open("/dev/null", O_RDWR);  /* 將0,1,2重定向到/dev/null */  
     dup(0);
     dup(0);
   }
--------------------------------------------------------------------------------------------------
初始化global全局變量
 global.stop      = 0;
 global.buf       = NULL;
 global.size      = 0;
 global.in.plugin = NULL;
--------------------------------------------------------------------------------------------------
同步全局圖像緩沖區:
 pthread_mutex_init(&global.db, NULL);
 pthread_cond_init(&global.db_update, NULL);
--------------------------------------------------------------------------------------------------
忽略SIGPIPE信號(當關(guān)閉TCP sockets時(shí),OS會(huì )發(fā)送該信號)
 signal(SIGPIPE, SIG_IGN);
--------------------------------------------------------------------------------------------------
注冊<CTRL>+C信號處理函數,來(lái)結束該程序
 signal(SIGINT, signal_handler);
 ------------------------------------------------------------------------------------------
  void signal_handler(int sig)
  {
    int i;
    /* signal "stop" to threads */
    LOG("setting signal to stop\n");
    global.stop = 1;
    usleep(1000*1000);
    /* clean up threads */
    LOG("force cancelation of threads and cleanup ressources\n");
    global.in.stop();
    for(i=0; i<global.outcnt; i++) {
      global.out[i].stop(global.out[i].param.id);
    }
    usleep(1000*1000);
    /* close handles of input plugins */
    dlclose(&global.in.handle);
    for(i=0; i<global.outcnt; i++) {
      dlclose(global.out[i].handle);
    }
    DBG("all plugin handles closed\n");
    pthread_cond_destroy(&global.db_update);
    pthread_mutex_destroy(&global.db);
    LOG("done\n");
    closelog();
    exit(0);
    return;
  }
 ------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
打開(kāi)輸入插件:
   tmp = (size_t)(strchr(input, ' ')-input);     
   global.in.plugin = (tmp > 0)?strndup(input, tmp):strdup(input); /* 在命令中獲得動(dòng)態(tài)庫 */
   global.in.handle = dlopen(global.in.plugin, RTLD_LAZY);  /* 打開(kāi)動(dòng)態(tài)鏈接庫 */
   global.in.init = dlsym(global.in.handle, "input_init");  /* 獲得動(dòng)態(tài)庫內的input_init()函數 */
   global.in.stop = dlsym(global.in.handle, "input_stop");  /* 獲得動(dòng)態(tài)庫內的input_stop()函數 */
   global.in.run = dlsym(global.in.handle, "input_run");   /* 獲得動(dòng)態(tài)庫內的input_run()函數 */
   /* try to find optional command */
   global.in.cmd = dlsym(global.in.handle, "input_cmd");   /* 獲得動(dòng)態(tài)庫內的input_cmd()函數 */
   global.in.param.parameter_string = strchr(input, ' ');  /* 將命令參數的起始地址賦給para.parameter_string,已經(jīng)去掉前賣(mài)弄的動(dòng)態(tài)庫 */
   global.in.param.global = &global;     /* 將global結構體的地址賦給param.global */
   global.in.init(&global.in.param);     /* 傳遞global.in.param給init,進(jìn)行初始化 */
   }
--------------------------------------------------------------------------------------------------
打開(kāi)輸出插件:
 for (i=0; i<global.outcnt; i++) {   /* 因為是一個(gè)輸入對應多個(gè)輸出,所以輸出采用了for循環(huán) */
  tmp = (size_t)(strchr(output[i], ' ')-output[i]);
  global.out[i].plugin = (tmp > 0)?strndup(output[i], tmp):strdup(output[i]);
  global.out[i].handle = dlopen(global.out[i].plugin, RTLD_LAZY);
  global.out[i].init = dlsym(global.out[i].handle, "output_init");
  global.out[i].stop = dlsym(global.out[i].handle, "output_stop");
  global.out[i].run = dlsym(global.out[i].handle, "output_run");
  /* try to find optional command */
  global.out[i].cmd = dlsym(global.out[i].handle, "output_cmd");
  global.out[i].param.parameter_string = strchr(output[i], ' ');
  global.out[i].param.global = &global;
  global.out[i].param.id = i;
  global.out[i].init(&global.out[i].param);
 }
--------------------------------------------------------------------------------------------------
開(kāi)始運行輸入插件的run()函數:
 global.in.run();
--------------------------------------------------------------------------------------------------
開(kāi)始運行輸出插件的run()函數:
 for(i=0; i<global.outcnt; i++)
  global.out[i].run(global.out[i].param.id);
--------------------------------------------------------------------------------------------------
運行完以上函數,該進(jìn)程進(jìn)入休眠狀態(tài),等待用戶(hù)按下<CTRL>+C結束所有的進(jìn)程:
 pause();
--------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
利用注釋及自定義加密免殺Webshell
入門(mén)級的病毒源碼[VC ]
wav2pcm
SQL的一些用法小結
Loadrunner message函數詳細分析
strtok.c函數
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久