/**@brief 仿照linux kfifo寫的ring buffer
*@atuher anker date:2013-12-18
* ring_buffer.h
* */
#ifndef kfifo_header_h
#define kfifo_header_h
#include #include #include #include #include #include //判斷x是否是2的次方
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
//取a和b中最小值
#define min(a, b) (((a) < (b)) ? (a) : (b))
struct ring_buffer
;//初始化緩衝區
struct ring_buffer* ring_buffer_init(void *buffer, uint32_t size, pthread_mutex_t *f_lock)
ring_buf = (struct ring_buffer *)malloc(sizeof(struct ring_buffer));
if (!ring_buf)
memset(ring_buf, 0, sizeof(struct ring_buffer));
ring_buf->buffer = buffer;
ring_buf->size = size;
ring_buf->in = 0;
ring_buf->out = 0;
ring_buf->f_lock = f_lock;
return ring_buf;
}//釋放緩衝區
void ring_buffer_free(struct ring_buffer *ring_buf)
free(ring_buf);
ring_buf = null;
}}//緩衝區的長度
uint32_t __ring_buffer_len(const struct ring_buffer *ring_buf)
//從緩衝區中取資料
uint32_t __ring_buffer_get(struct ring_buffer *ring_buf, void * buffer, uint32_t size)
//向緩衝區中存放資料
uint32_t __ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
uint32_t ring_buffer_len(const struct ring_buffer *ring_buf)
uint32_t ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
uint32_t ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
#endif
採用多執行緒模擬生產者和消費者編寫測試程式,如下所示:
/**@brief ring buffer測試程式,建立兩個執行緒,乙個生產者,乙個消費者。
* 生產者每隔1秒向buffer中投入資料,消費者每隔2秒去取資料。
*@atuher anker date:2013-12-18
* */
#include "ring_buffer.h"
#include #include #define buffer_size 1024 * 1024
typedef struct student_info
student_info;
void print_student_info(const student_info *stu_info)
student_info * get_student_info(time_t timer)
srand(timer);
stu_info->stu_id = 10000 + rand() % 9999;
stu_info->age = rand() % 30;
stu_info->score = rand() % 101;
print_student_info(stu_info);
return stu_info;
}void * consumer_proc(void *arg)
return (void *)ring_buf;
}void * producer_proc(void *arg)
return (void *)ring_buf;
}int consumer_thread(void *arg)
return tid;
}int producer_thread(void *arg)
return tid;
}int main()
buffer = (void *)malloc(buffer_size);
if (!buffer)
size = buffer_size;
ring_buf = ring_buffer_init(buffer, size, f_lock);
if (!ring_buf)
#if 0
student_info *stu_info = get_student_info(638946124);
ring_buffer_put(ring_buf, (void *)stu_info, sizeof(student_info));
stu_info = get_student_info(976686464);
ring_buffer_put(ring_buf, (void *)stu_info, sizeof(student_info));
ring_buffer_get(ring_buf, (void *)stu_info, sizeof(student_info));
print_student_info(stu_info);
#endif
printf("multi thread test.......\n");
produce_pid = producer_thread((void*)ring_buf);
consume_pid = consumer_thread((void*)ring_buf);
pthread_join(produce_pid, null);
pthread_join(consume_pid, null);
ring_buffer_free(ring_buf);
free(f_lock);
return 0;
}
總結:len = min(len, fifo->size - fifo->in + fifo->out);
在len和(fifo->size - fifo->in + fifo->out)之間取乙個較小的值賦給len。注意,當(fifo->in == fifo->out+fifo->size)時,表示緩衝區已滿,此時得到的較小值一定是0,後面實際寫入的位元組數也全為0。
另一種邊界情況是當len很大時(因為len是無符號的,負數對它來說也是乙個很大的正數),這一句也能保證len取到乙個較小的值,因為fifo->in總是大於等於fifo->out,所以後面的那個表示式l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));的值不會超過fifo->size的大小。
smp_mb(); smp_wmb();是加記憶體屏障,這裡不是我們討論的範圍,你可以忽略它。
l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));是把上一步決定的要寫入的位元組數len「切開」,這裡又使用了乙個技巧。注意:實際分配給fifo->buffer的位元組數fifo->size,必須是2的冪,否則這裡就會出錯。既然fifo->size是2的冪,那麼(fifo->size-1)也就是乙個後面幾位全為1的數,也就能保證(fifo->in & (fifo->size - 1))總為不超過(fifo->size - 1)的那一部分,和(fifo->in)% (fifo->size - 1)的效果一樣。
這樣後面的**就不難理解了,它先向 fifo->in 到緩衝區末端這一塊寫資料,如果還沒寫完,在從緩衝區頭開始寫入剩下的,從而實現了迴圈緩衝。最後,把寫指標後移 len 個位元組,並返回len。
從上面可以看出,fifo->in的值可以從0變化到超過fifo->size的數值,fifo->out也如此,但它們的差不會超過fifo->size。
編寫乙個makefile
什麼是makefile?對於大多數的windows程式設計師來講,makefile可能不是那麼重要,因為windows的ide都為程式設計師做好了這個工作。但是在linux下程式設計,會不會寫makefile,從側面上說明乙個人是否具備完成大型工程的能力。makefile的作用 makefile是用...
編寫乙個webpack loader
loader是一種打包的方案,webpack預設只識別js結尾的檔案,當遇到其他格式的檔案後,webpack並不知道如何去處理。此時,我們可以定義一種規則,告訴webpack當他遇到某種格式的檔案後,去求助於相應的loader。新建loaders資料夾並建立三個loaders檔案 remove co...
乙個簡單的程序 跳到ring3
typedef unsigned int u32 typedef unsigned short u16 typedef unsigned char u8 typedef struct descriptor 8 a?descriptor void set gdt desc struct desc st...