DPDK(三):入門2---DPDK部分代碼解釋

1、access函數
1.函數功能:
檢查調用進程是否能夠對指定的文件執行某種操做。
2.函數原型:
1)函數頭文件
#include <stdio.h>
#include <unistd.h>
int access(const char * pathname, int mode)
3)形參
pathname:須要檢測的文件路勁名
mode:須要測試的操做模式。
4)函數返回值說明
成功執行時,返回0。失敗返回-1,errno被設爲如下的某個值 
EINVAL: 模式值無效 
EACCES: 文件或路徑名中包含的目錄不可訪問 
ELOOP : 解釋路徑名過程當中存在太多的符號鏈接 
ENAMETOOLONG:路徑名太長 
ENOENT:路徑名中的目錄不存在或是無效的符號鏈接 
ENOTDIR: 路徑名中看成目錄的組件並不是目錄 
EROFS: 文件系統只讀 
EFAULT: 路徑名指向可訪問的空間外 
EIO:輸入輸出錯誤 
ENOMEM: 不能獲取足夠的內核內存 
ETXTBSY:對程序寫入出錯
5)mode說明
R_OK 測試讀許可權
W_OK 測試寫許可權
X_OK 測試執行許可權
F_OK 測試文件是否存在
3.函數實例
access("test.txt", F_OK)==0) printf("File exist\n");linux

2、__attribute__ 機制詳解
__attribute__ 能夠設置函數屬性(Function Attribute )、變量屬性(Variable Attribute )和類型屬性(Type Attribute )。
_attribute__ 語法格式爲:__attribute__ ((attribute-list)),其位置約束爲:放於聲明的尾部「 ;」 以前。
一、對結構體(struct )或共用體(union )進行屬性設置。
大體有六個參數值能夠被設定,即:aligned(字節對齊), packed(取消字節對齊即一字節對齊), transparent_union(弱類型的聯合體), unused(變量或函數可能不使用,避免編譯告警), deprecated (不提倡使用的函數或變量,編譯器必須生成警告)和 may_alias 。
(1)aligned
struct m
{
char a;
int b;
short c;
}__attribute__((aligned(4))) mm;
(2)packed
typedef struct {
    double x;
    double y;
} __attribute__((packed)) position_t;
(3)transparent_union
typedef union {
int i ;
float f;
}U __attribute__((transparent_union));
void foo (U u)
{
static int s;
s += u.i;
printf("s = %d\n",s);
}
void caller(void){
foo(1);
foo(1.0f);
}
int main(void){
caller();
}
(4)unused
__attribute__((unused)) static void a(void)
{

printf("a\n");
}
}
二、函數屬性(Function Attribute)
GNU CC編譯選項添加 –Wall打開全部告警,函數屬性能夠幫助開發者把一些特性添加到函數聲明中,從而可使編譯器在錯誤檢查方面的功能更強大。
下面介紹幾個常見的函數屬性:
(1)__attribute__ format,該__attribute__屬性能夠給被聲明的函數加上相似printf或者scanf的特徵,它可使編譯器檢查函數聲明和函數實際調用參數之間的格式化字符串是否匹配。
具體使用格式以下:
format (archetype, string-index, first-to-check)
__attribute__((format(printf,m,n)))
__attribute__((format(scanf,m,n)))
其中參數m與n的含義爲:
m:第幾個參數爲格式化字符串(format string);
n:從函數的第幾個參數開始按上述規則進行檢查,即參數「…」裏的第一個參數在函數參數總數排在第幾。
舉例:有參數不匹配的狀況就會報編譯告警。
1:程序員

2:extern void myprint(const char *format,...)
_
__attribute__((format(printf,1,2)));數組

3:
4:void test()緩存

5:{服務器

6: myprint("i=%d\n",6);dom

7: myprint("i=%s\n",6);socket

8: myprint("i=%s\n","abc");函數

9: myprint("%s,%d,%d\n",1,2);性能

10:}測試

運行$gcc –Wall –c attribute.c attribute後,輸出結果爲:

attribute.c: In function `test':
attribute.c:7: warning: format argument is not a pointer (arg 2)
attribute.c:9: warning: format argument is not a pointer (arg 2)
attribute.c:9: warning: too few arguments for format
(2)__attribute__ noreturn
該屬性通知編譯器函數從不返回值,當遇到相似函數須要返回值而卻不可能運行到返回值處就已經退出來的狀況,該屬性能夠避免出現錯誤信息。C庫函數中的abort()和exit()的聲明格式就採用了這種格式。
例如:extern void myexit() __attribute__((noreturn));以後,編譯不會再出現警告信息。
(3)__attribute__ const
該屬性只能用於帶有數值類型參數的函數上。當重複調用帶有數值參數的函數時,因爲返回值是相同的,因此此時編譯器能夠進行優化處理,除第一次須要運算外, 其它只須要返回第一次的結果就能夠了,進而能夠提升效率。
extern int square(int n) __attribute__ ((const));
...
for (i = 0; i < 100; i++ )  {
       total += square (5) + i;            

經過添加__attribute__((const))聲明,編譯器只調用了函數一次,之後只是直接獲得了相同的一個返回值。
const參數不能用在帶有指針類型參數的函數中,由於該屬性不但影響函數的參數值,一樣也影響到了參數指向的數據,它可能會對代碼自己產生嚴重甚至是不可恢復的嚴重後果。
(4)__attribute__ constructor/destructor
若函數被設定爲constructor屬性,則該函數會在 main()函數執行以前被自動的執行。相似的,若函數被設定爲destructor屬性,則該函數會在main()函數執行以後或者exit()被調用後被自動的執行。擁有此類屬性的函數常常隱式的用在程序的初始化數據方面。
__attribute__((constructor)) void before_main() {

printf("--- %s\n", __func__);
}
}


__attribute__((destructor)) void after_main() {

printf("--- %s\n", __func__);
}
}

int main(int argc, char **argv) {

printf("--- %s\n", __func__);

exit(0);

printf("--- %s, exit ?\n", __func__);


return 0;
}
}
執行結果:
--- before_main

--- main

--- after_main
3、gcc的__builtin_函數介紹
一、__builtin_prefetch() 說明
原型:void __builtin_prefetch (const void *addr, ...)
__builtin_prefetch() 是 gcc 的一個內置函數。這個函數爲流操做實現預抓取機制。使用這個函數一般能夠減小緩存缺失和停頓,從而提升性能。但該函數也須要 CPU 的支持。

其中參數 addr 是個內存指針,它指向要預取的數據,咱們人工須要斷定這些數據是很快能訪問到的,或者說是它們就在最近的內存中 --- 通常來講,對於鏈表而言,各個節點在內存中基本上是緊挨着的,因此咱們容易預取鏈表節點裏的指針項。
該函數還有兩個可選參數,rw 和 locality 。
rw 是個編譯時的常數,或 1 或 0 。1 時表示寫(w),0 時表示讀(r) 。
locality 必須是編譯時的常數,也稱爲「時間局部性」(temporal locality) 。時間局部性是指,若是程序中某一條指令一旦執行,則不久以後該指令可能再被執行;若是某數據被訪問,則不久以後該數據會被再次訪問。該值的範圍在 0 - 3 之間。爲 0 時表示,它沒有時間局部性,也就是說,要訪問的數據或地址被訪問以後的不長的時間裏不會再被訪問;爲 3 時表示,被訪問的數據或地址具備高 時間局部性,也就是說,在被訪問不久以後很是有可能再次訪問;對於值 1 和 2,則分別表示具備低 時間局部性 和中等 時間局部性。該值默認爲 3 。
二、__builtin_constant_p (exp)說明
判斷exp是否在編譯時就能夠肯定其爲常量,若是exp爲常量,該函數返回1,不然返回0。
三、__builtin_expect 說明
這個指令是GCC (version >= 2.96)提供給程序員使用的,做用是容許程序員將最有可能執行的分支告訴編譯器。這樣編譯器能夠對代碼進行優化,以減小指令跳轉帶來的性能降低。

這個指令的寫法爲:__builtin_expect(EXP, N)。
意思是:EXP==N的機率很大。
通常的使用方法是將__builtin_expect指令封裝爲likely和unlikely宏。這兩個宏的寫法以下.
#define likely(x) __builtin_expect(!!(x), 1) //x極可能爲真
#define unlikely(x) __builtin_expect(!!(x), 0) //x極可能爲假
首先要明確:
if(likely(value)) //等價於 if(value)

if(unlikely(value)) //也等價於 if(value)進一步瞭解原理能夠反彙編看一下函數的跳轉順序,參考文檔:https://blog.csdn.net/grublinux/article/details/37543489四、__builtin_ffs(x):返回x中最後一個爲1的位是從後向前的第幾位,如__builtin_ffs(0x789)=1, __builtin_ffs(0x78c)=3。五、__builtin_popcount(x):x中1的個數。六、__builtin_parity(x):x中1的奇偶性。七、__builtin_return_address(n):當前函數的第n級調用者的地址,用的最多的就是__builtin_return_address(0),即得到當前函數的調用者的地址。八、__builtin_types_compatible_p(type1, type2):判斷type1和type2是不是相同的數據類型,相同返回1,不然返回0。該函數不區分const/volatile這樣的修飾符,即int和const int被認爲是相同的類型。4、5、asm volatile6、pipe#include<unistd.h>int pipe(int filedes[2]);返回值:成功,返回0,不然返回-1。參數數組包含pipe使用的兩個文件的描述符。fd[0]:讀管道,fd[1]:寫管道。必須在fork()前調用pipe(),不然子進程不會繼承文件描述符。兩個進程不共享祖先進程,就不能使用pipe。可是可使用命名管道,下面介紹。當管道進行寫入操做的時候,若是寫入的數據小於128K則是非原子的,若是大於128K字節,緩衝區的數據將被連續地寫入管道,直到所有數據寫完爲止,若是沒有進程讀取數據,則將一直阻塞。二、命名管道FIFO與管道不一樣的是:每一個FIFO都有一個路徑與之關聯,從而容許無親緣關係的進程訪問。#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);這裏pathname是路徑名,mode是sys/stat.h裏面定義的建立文件的權限.fifo時須要注意:fifo管道是先調用mkfifo建立,而後再用open打開獲得fd來使用.在打開fifo時要注意,它是半雙工的的,通常不能使用O_RDWR打開,而只能用只讀或只寫打開.   fifo能夠用在非親緣關係的進程間,而它的真正用途是在服務器和客戶端之間. 因爲它是半雙工的因此,若是要進行客戶端和服務器雙方的通訊的話,每一個方向都必須創建兩個管道,一個用於讀,一個用於寫。三、socketpair#include <sys/types.h>#include <sys/socket.h>int socketpair(int domain, int type, int protocol, int sv[2]);參數1(domain):表示協議族,在Linux下只能爲AF_LOCAL或者AF_UNIX。(自從Linux 2.6.27後也支持SOCK_NONBLOCK和SOCK_CLOEXEC) 參數2(type):表示協議,能夠是SOCK_STREAM或者SOCK_DGRAM。SOCK_STREAM是基於TCP的,而SOCK_DGRAM是基於UDP的 參數3(protocol):表示類型,只能爲0 參數4(sv[2]):套節字柄對,該兩個句柄做用相同,均能進行讀寫雙向操做 返回結果: 0爲建立成功,-1爲建立失敗,而且errno來代表特定的錯誤號,具體錯誤號以下所述:使用注意:該函數只能用於UNIX域(LINUX)下。 只能用於有親緣關係的進程(或線程)間通訊。 所建立的套節字對做用是同樣的,均可以可讀可寫(而管道PIPE只能進行單向讀或寫)。 在讀的時候,管道內必須有內容,不然將會阻塞;簡而言之,該函數是阻塞的。

相關文章
相關標籤/搜索