關鍵在於寫指標不能追上讀指標,讓讀指標和寫指標保留乙個位元組的距離來區分2個指標重疊的情況。
如何保證執行緒安全的?
其實就是某個執行緒在讀取或者寫入的時候取的某個時間點的指標來判斷時候符合條件,條件只能是越來越好,而不可能是越來越差。比如判斷能夠寫入的時候,空間肯定是越來越多的
//實際的緩衝區大小要多乙個位元組
struct ringbuffer
;//實際的緩衝區大小要多乙個位元組
void ip_reset_ringbuffer(ringbuffer* pringbuffer)
ringbuffer* ip_create_ringbuffer(int buffersize)
else
memset( pringbuffer ->m_pbuffer, 0, buffersize);
pringbuffer ->m_phead = pringbuffer ->m_pbuffer;
pringbuffer ->m_ptail = pringbuffer ->m_pbuffer + buffersize;
pringbuffer ->m_pread = pringbuffer ->m_pwrite = pringbuffer ->m_phead;
return pringbuffer;
}//在某個時間點由寫執行緒先判斷緩衝區是否有足夠的空間進行寫操作
//寫指標在追趕讀指標的時候, 必須和讀指標保持1個位元組的間距,
//不能趕上讀指標
bool ip_checkcanwrite_ringbuffer(ringbuffer* pringbuffer, int checksize)
//需要再加上從緩衝頭部到讀指標的距離, 這個時候要算加起來的長度
//且需要多算1個位元組, 防止寫指標在追趕讀指標的時候重疊
//由於讀指標在寫指標後面,必然不會操作寫指標, 這裡可以實時取讀指標
//這個時候可能讀執行緒又讀了資料
else
else}}
//寫指標跑的較快
//這裡不能取實時的讀指標, 因為可能讀執行緒導致讀指標又跑到了寫指標的後面
else
else
}
}//該函式必須先進行剩餘空間檢查後才能進行寫操作
//check函式已經保證了必然有足夠的1500位元組
void ip_pushdata_ringbuffer(ringbuffer* pringbuffer, char* pdata, int length, int maxfree)
else
}//末尾的空間不夠,還要拷貝到陣列頭
else
}//寫指標小於讀指標
else
}//在緩衝區上試圖找到乙個完整的ip包然後傳送
static void sendippacket(tunwriter* ptunwriter, ringbuffer* pringbuffer, int tundevicefd)
//夠乙個ip包的首部
else if (left >= 20)
//不足乙個完整的ip包
else}}
//讀指標在寫指標的前面, 寫指標肯定不會趕上讀指標,這裡可以取實時的寫指標
else
//夠乙個ip包的首部
else if (left >= 20)
//有一部分在末尾, 一部分在頭部
else
//取該ip包的長度
pbegin = psendbuffer;
//末尾剩餘資料報長度
part = pringbuffer ->m_ptail - pringbuffer ->m_pread;
ipacketlength = ntohs(*((unsigned short *)(pbegin + 2)));
itotallength = ipacketlength;
//足夠乙個完整的ip包
if (left >= ipacketlength)
//不夠,要再從緩衝頭部拷貝
else
//進入傳送環節
goto send;
}//不足乙個完整的ip包
else}}
send:
int isendtun = write(tundevicefd, psendbuffer, ipacketlength);
if ((-1 == isendtun) && (errno == eintr))
//出現下面兩種情況,表示tun裝置不可寫入,就不需要讀取操作了
else if ((-1 == isendtun) && (errno == ewouldblock))
else if ((-1 == isendtun) && (errno != eintr) && (errno != ewouldblock))
//傳送成功
else
}
環形資料緩衝結構
生產者消費者模式下的可覆蓋環形資料緩衝結構 1 簡介 生產者 消費者模式是軟體架構中最常用到的模式,在實際的軟體開發過程中,經常會碰到如下場景 某個模組負責產生資料,這些資料由另乙個模組來負責處理 此處的模組是廣義的,可以是類 函式 執行緒 程序等 產生資料的模組,就形象地稱為生產者 而處理資料的模...
環形緩衝區的實現
乙個簡單的環形緩衝區,沒有寫加解鎖的部分,用於多執行緒的話還是自己加吧.pragma once include stdio.h include stdlib.h include memory.h namespace linker ring bool put elementtype e else bo...
環形緩衝區的c實現
標頭檔案 ifndef xbuf h define xbuf h define xbufdefaultsize 1024 1024 緩衝區預設大小 typedef unsigned int uint32 建立乙個環形緩衝區 size為緩衝區大小 void x buf create uint32 si...