linux&項目知識點總結

我太鹹魚了,一個月前制定的計劃,現在還沒完成。我決定把要寫的先寫在這裏,免得我忘記了。

  • 無鎖循環隊列kfifo
  • CPU親和性設定
  • 設置大小端判定宏
  • 安裝OCCI,zlib,libpcap(centos7)

1 實現無鎖環形隊列kfifo。(雖然我知道他只能實現單消費者單生產者,但是 看看 DPDK ring的實現或許可以 整一個好一點的)
2 CPU親和性設定
linuxC語言裏有 將線程綁定到特定CPU核的方法。通過這個方法或許可以避免上下文切換(關鍵是 問題可以被 多線程處理切分而不出現問題,就好像矩陣乘法那樣)
linux中的線程:linux裏是沒有線程的。所有的線程都是 用LWP(輕量級進程)來模擬的。linux裏有一個進程號,兩個線程號。分別是

進程pid: getpid()                 
POSIX線程tid: pthread_self()     //進程內唯一,但是在不同進程則不唯一。因爲是POSIX標準的線程號(我的理解是  封裝了操作系統的API使之統一)。
線程pid: syscall(__NR_gettid)     //系統內是唯一的
或者 syscall(SYS_gettid) 

對於單線程的進程,內核中tid==pid,對於多線程進程,他們有相同的pid,不同的tid。tid用於描述內核真實的pid和tid信息(轉)
pthread_self返回的是posix定義的線程ID,man手冊明確說明了和內核線程tid不同。它只是用來區分某個進程中不同的線程,當一個線程退出後,新創建的線程可以複用原來的id。 而 這三個 線程pid是可以保證操作系統都不一樣的。

gettid 獲取的是內核中真實線程ID, 對於多線程進程來說,每個tid實際是不一樣的。
而pthread_self獲取的是相對於進程的線程控制塊的首地址, 只是用來描述統一進程中的不同線程,
例子中,在線程中調用fork,只會將當前活動線程設置爲活動(其他線程終止),且進程使用的都是虛擬地址,所以產生的pthread_self() 是相同的。(轉)

上述不匹配,對程序的實際運行,並沒有影響,因爲他們的tid是不同的
關於這三個的介紹,參見這個博客
https://blog.csdn.net/rsyp2008/article/details/45150621
POSIX標準介紹如下:https://www.cnblogs.com/1130136248wlxk/articles/5308863.html
具體代碼如下:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/syscall.h> // 你要注意 整 這個 __NR_gettid 需要這個頭文件。
using namespace std;

/* sysconf( _SC_NPROCESSORS_CONF ) 查看cpu的個數;打印用%ld長整。
 * sysconf( _SC_NPROCESSORS_ONLN ) 查看在使用的cpu個數;打印用%ld長整 */
void *cosumer(void *args){
int *m=(int*)args;
cpu_set_t mask;
cout<<*m<<endl;
CPU_ZERO(&mask);    /* 初始化set集,將set置爲空*/
    CPU_SET(*m, &mask);
 pthread_setaffinity_np(pthread_self(),sizeof(mask), &mask);
 // 將當前 線程綁定到 mask裏的core編號裏,你要知道我每次都用的不同的m。    
   long long mm=pthread_self();
   if(*m==0)
   cout<<"*"<<*m<<"???"<<"*"<<getpid()<<"*"<<getgid()<<"*"<<mm<<"*"<<"*"<<syscall(__NR_gettid)<<endl;
   else
    cout<<"*"<<*m<<"?????"<<"*"<<getpid()<<"*"<<getgid()<<"*"<<mm<<"*"<<"*"<<syscall(__NR_gettid)<<endl;
    // 依次是pid ,getgid是進程組號()。
    /// syscall是  系統線程號。
   cpu_set_t get;// 查詢 綁定情況。
CPU_ZERO(&get);
    int tt=0;
     
    pthread_getaffinity_np(pthread_self(), sizeof(get), &get) ;// 綁定core
        //printf("get CPU affinity failue, ERROR:%s\n", strerror(errno));  
    /*查看運行在當前進程的cpu*/
    for(int i = 0; i < 2; i++) {
        if (CPU_ISSET(i, &get)) { /*查看cpu i 是否在get 集合當中*/
            printf("this process %d of running processor: %d %lld %d\n", getpid(), i,pthread_self(),syscall(__NR_gettid)); 
        }    
    }

     return NULL;
}
int main(int argc, char **argv)
{    cout<<"???"<<" "<<getpid()<<" "<<getgid()<<" "<<endl;
    int cpus = 0;
    int  i = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_CONF);
    printf("cpus: %d\n", cpus);

    CPU_ZERO(&mask);    /* 初始化set集,將set置爲空*/
    CPU_SET(0, &mask);  /* 依次將0、1、2、3號cpu加入到集合,前提是你的機器是多核處理器*/
    CPU_SET(1, &mask);
    //CPU_SET(2, &mask);
    //CPU_SET(3, &mask);
    
    /*設置cpu 親和性(affinity)*/
     pthread_t x[2];
    //cout<<"wwww"<<endl;
     int a[2]={0,1};
    
    for(int i=0;i<2;i++){
       
        int ret=pthread_create(&x[i],NULL,cosumer,(void *)(&a[i]));
      //pthread_join(x[i],0);
       //cout<<pthread_self()
         if(ret==1){puts("w");continue;}
         //pthread_setaffinity_np(x[i],sizeof(mask), &mask);
    }
    /*if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
        printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    } 
   */  
    usleep(1000); /* 讓當前的設置有足夠時間生效*/
    /*查看當前進程的cpu 親和性*/
    CPU_ZERO(&get);
//cout<<"2222222"<<endl;
    int tt=0;
     
    pthread_getaffinity_np(x[tt], sizeof(get), &get) ;
        //printf("get CPU affinity failue, ERROR:%s\n", strerror(errno));
             
//return -1; 
    /*查看運行在當前進程的cpu*/
    for(i = 0; i < cpus; i++) {

        if (CPU_ISSET(i, &get)) { /*查看cpu i 是否在get 集合當中*/
            printf("this process %d of running processor: %d %lld\n", getpid(), i,pthread_self()); 
        }    
    }
    sleep(3); //讓程序停在這兒,方便top命令查看
       
    return 0;
}

在這裏插入圖片描述
註釋:這兩個線程的輸出成功的亂序了。
2843 是 主線程號。1000是主線程 組號
cpu核心數爲2(我的虛擬機我就分了2)
第一個線程的 tid 爲2843, posix線程id爲139976734291712 內核線程id爲2844
第二個線程 的tid爲2843 poix爲139976725899008 內核線程id爲2845。
並且 通過查詢發現 綁定成功。okey

3大小端宏的設定:
我假定libpcap已經解決大小端宏的問題了(網絡傳輸是大端,而如果電腦是小端,那麼如何處理包)
②那個關鍵的宏定義 WORDS_BIGENDIAN 在libpcap裏是否有
我的傾向是沒有,因爲如果有,那麼我上一次的代碼,裏面的ip報頭中有關於就應該正確的運行,代碼部分:

#ifdef WORDS_BIGENDIAN
  u_int8_t ip_version:4.
           ip_header_length:4;
#else 
    u_int8_t ip_header_length:4.
            ip_version:4;
 #endif                     

不能運行,所以我懷疑這個 關鍵字得自己定義。(此處存疑。這部分代碼來源於 網絡安全開發包詳解)
於是手工判斷大小端,參照linux源碼
大端:低位在前。比如0x12345678
存儲爲 0x78 0x56 0x34 0x12
小端爲 0x12 0x34 0x56 0x78

   #include <iostream>
#include <bits/stdc++.h>
#define kkk 10
#define ENDIANNESS ((char)endian_test.l)
using namespace std;

static union {
    char c[4];
    unsigned long l;
} endian_test= { { 'l', '?', '?', 'b' } };
int main()
{   if('b'==ENDIANNESS){
       #define big
    }// 如果定義了這個宏,就是大端。之所以這麼寫
    #ifdef big
       printf("大端啊哥哥");
    #else
       printf("dd");
    #endif
    return 0;
}

https://www.cnblogs.com/wawahaha/p/3821486.html (libpcap)
https://blog.csdn.net/sirria1/article/details/83115582(zlib)
https://blog.csdn.net/freeking101/article/details/55506897(oralcle連接代碼)
https://blog.csdn.net/wjb123sw99/article/details/83863234(occi)

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