在linux下所有設備都是文件。所以對攝像頭的操作其實就是對文件的操作。USB攝像頭的設備文件就是在/dev目錄下的video0(假如只有一個攝像頭)。在linux下操作攝像頭就是使用v4l2對攝像頭進行的操作,操作步驟如下
打開設備文件。
int fd=open(」/dev/video0″,O_RDWR);
2. 取得設備的capability,看看設備具有什麼功能,比如是否具有輸入,或者音頻輸入輸出等。VIDIOC_QUERYCAP,struct v4l2_capability
v4l2_std_id std;
do {
ret= ioctl(fd, VIDIOC_QUERYSTD, std);
} while (ret == -1 errno == EAGAIN);
switch (std) {
case V4L2_STD_NTSC:
//……
case V4L2_STD_PAL:
//……
}
3. 選擇輸入,一個設備可以有多個輸入。VIDIOC_S_INPUT,struct v4l2_input(可不要)
4. 設置的制式和幀格式,制式包括PAL,NTSC,幀的格式個包括寬度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
struct v4l2_format fmt;
memset ( fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, fmt) < 0)
{
printf("set format failed ");
//return 0;
}
5. 向驅動申請幀緩沖,一般不超過5個。struct v4l2_requestbuffers
struct v4l2_requestbuffers req;
memset(req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS,req) == -1)
{
perror("VIDIOC_REQBUFS error ");
//return -1;
}
6.申請物理內存
將申請到的幀緩沖映射到用戶空間,這樣就可以直接操作採集到的幀了,而不必去復制。將申請到的幀緩沖全部入隊列,以便存放採集到的數據.VIDIOC_QBUF,struct v4l2_buffer
VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf("sizeof(VideoBuffer) is %d ",sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset( buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, buf) < 0)
{
printf("VIDIOC_QUERYBUF error ");
//return -1;
}
printf("buf len is %d ",sizeof(buf));
//內存映射
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d ",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf("buf2 len is %d ",sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED)
{
perror("buffers error ");
//return -1;
}
if (ioctl (fd, VIDIOC_QBUF, buf) < 0)
{
printf("VIDIOC_QBUF error ");
//return -1;
}
}
7. 開始的採集。
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, type) < 0)
{
printf("VIDIOC_STREAMON error ");
// return -1;
}
8. 出隊列以取得已採集數據的幀緩沖,取得原始採集數據。VIDIOC_DQBUF, 將緩沖重新入隊列尾,這樣可以循環採集。VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, buf) < 0)
{
perror("VIDIOC_DQBUF failed. ");
//return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
unsigned char *ptcur = buffers[numBufs].start;
DEBUG("buf.bytesused = %d ",buf.bytesused);
int i1;
for(i1=0; i1<buf.bytesused; i1++)
{
if((buffers[numBufs].start[i1] == 0xFF) (buffers[numBufs].start[i1+1] == 0xC4))
{
DEBUG("huffman table finded! buf.bytesused = %d FFC4 = %d ",buf.bytesused,i1);
break;
}
}
if(i1 == buf.bytesused)printf("huffman table don't exist! ");
int i;
for(i=0; i<buf.bytesused; i++)
{
if((buffers[numBufs].start[i] == 0xFF) (buffers[numBufs].start[i+1] == 0xD8)) break;
ptcur++;
}
DEBUG("i=%d,FF=%02x,D8=%02x ",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
int imagesize =buf.bytesused - i;
DEBUG("buf.bytesused = %d ",buf.bytesused);
DEBUG ("imagesize = %d ",imagesize);
9. 停止的採集。VIDIOC_STREAMOFF
10. 關閉設備。close(fd);
❷ Linux v4l2圖片採集問題
源碼中:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ioctl (fd, VIDIOC_S_FMT, &fmt);
指定了採集圖像的格式為YUYV格式。
要像採集成JPEG圖像,得查詢一下攝像頭是否有相應功能,如果沒有相應功能即使將fmt設置為jpeg最終採集到的還是yuyv格式。
yuyv可以轉換為bmp數據,然後調用jpeglib庫轉換為jpg圖像,稍稍有些麻煩,但沒辦法硬體不足就要用軟體來彌補了。
至於你說的read沒讀到數據,我現在沒有開發環境,沒法測試。
❸ fmt(2)是什麼意思
Slice重傳。
fmt(2)是Slice重傳的意思。
fmt是一種Linux命令,用來編排文本文件,也是指用可編程、多功能的數字控制設備更換剛性自動化設備,用易編程、易修改、易擴展、易更換的軟體控制代替剛性聯結的工序過程,使剛性生產線實現軟性化和柔性化,能夠快速響應市場的需求,多快好省地完成多品種、中小批量地生產任務。
fmt命令用於編排文本文件,其會從指定的文件里讀取內容,將其依照指定格式重新編排後,輸出到標准輸出設備。
❹ Linux中與安全審計有關的函數
我的答案是最正確的 請採納我的內核審計系統的介面函數在Linux內核需要輸出審計信息時,它先調用函數audit_log_start創建緩沖區。接著,調用函數audit_log或audit_log_format寫緩沖區寫入審計信息,最後調用函數audit_log_end發送審計信息,並釋放緩沖區。這三個函數分別說明如下:1.函數audit_log_start 函數audit_log_start申請審計緩沖區,如果任務當前在系統調用中,系統調用被標識為可審計的,並在系統調用退出時,產生一條審計記錄。函數audit_log_start的參數ctx為審計上下文結構實例;參數gfp_mask為分配內存的類型,如:__GFP_WAIT表示可以等待和重調度;參數type為審計消息類型。如果緩存區申請成功,它返回審計緩沖區的指針,否則返回NULL表示錯誤。函數audit_log_start申請審計緩沖區,當審計緩沖區鏈表的緩沖區個數超過上限時,當前進程需要等待用戶空間的後台進程將審計消息寫入log文件,直到緩沖區個數小於上限值為止。函數audit_log_start在申請並初始化審計緩沖區後,給緩沖區加時間戳和審計記錄序列號。函數audit_log_start列出如下(在linux26/kernel/audit.c中)://聲明等待隊列頭,用於等待審計消息被後台進程寫入log文件static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,int type){struct audit_buffer*ab= NULL;struct timespect;unsigned intserial;int reserve;unsigned long timeout_start = jiffies; //開始的時間if (!audit_initialized)//如果已初始化,就直接退出return NULL;if (unlikely(audit_filter_type(type)))return NULL;if (gfp_mask & __GFP_WAIT)reserve = 0;elsereserve = 5; /*允許調用者多出5個條目*/ //當鏈表中審計緩沖區數超出上限時,進程等待auditd處理鏈表中緩沖區while (audit_backlog_limit&& skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {/* 等待後台進程auditd從隊列中處理部分緩沖區 */DECLARE_WAITQUEUE(wait, current);set_current_state(TASK_INTERRUPTIBLE); //設置當前進程的狀態為可中斷等待狀態add_wait_queue(&audit_backlog_wait, &wait); //將當前進程加入等待隊列if (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit)schele_timeout(timeout_start + audit_backlog_wait_time - jiffies);//調度__set_current_state(TASK_RUNNING);//設置當前進程為運行狀態remove_wait_queue(&audit_backlog_wait, &wait);continue;} //檢查每秒發送的記錄數不能超過上限,以防止受非法攻擊if (audit_rate_check())printk(KERN_WARNING "audit: audit_backlog=%d > " "audit_backlog_limit=%d\n", skb_queue_len(&audit_skb_queue), audit_backlog_limit);audit_log_lost("backlog limit exceeded");audit_backlog_wait_time = audit_backlog_wait_overflow;wake_up(&audit_backlog_wait);return NULL;}ab = audit_buffer_alloc(ctx, gfp_mask, type);//申請審計緩沖區if (!ab) {audit_log_lost("out of memory in audit_log_start");return NULL;}//得到當前時間存入t,計算審計記錄的序列號,存入serialaudit_get_stamp(ab->ctx, &t, &serial); //將時間戳和序列號寫入審計記錄audit_log_format(ab, "audit(%lu.%03lu:%u): ", t.tv_sec, t.tv_nsec/1000000, serial);return ab;}函數audit_buffer_alloc申請審計緩沖區,先嘗試從空閑鏈表上取下一個緩沖區,如果空閑鏈表中沒有,就分配一個緩沖區。然後,填充netlink消息頭。該函數列出如下: static DEFINE_SPINLOCK(audit_freelist_lock);//定義自旋鎖,用於鎖住鏈表audit_freeliststatic struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,gfp_t gfp_mask, int type){unsigned long flags;struct audit_buffer *ab = NULL;struct nlmsghdr *nlh; //從空閑鏈表中得到一個緩沖區spin_lock_irqsave(&audit_freelist_lock, flags);//加鎖if (!list_empty(&audit_freelist)) {ab = list_entry(audit_freelist.next,struct audit_buffer, list);list_del(&ab->list);--audit_freelist_count;}spin_unlock_irqrestore(&audit_freelist_lock, flags);//釋放鎖 //如果空閑鏈表中沒有空閑緩沖區成員,就分配一個緩沖區if (!ab) {ab = kmalloc(sizeof(*ab), gfp_mask);if (!ab)goto err;}ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);//分配套接字緩沖區if (!ab->skb)goto err;ab->ctx = ctx;ab->gfp_mask = gfp_mask; //擴展套接字緩沖區skb的已使用數據區,將netlink消息頭數據nlmsghdr加到skbnlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));nlh->nlmsg_type = type;nlh->nlmsg_flags = 0;nlh->nlmsg_pid = 0;nlh->nlmsg_seq = 0;return ab;err:audit_buffer_free(ab);return NULL;}2.函數audit_log_format函數audit_log_format將一個審計消息按格式寫入審計緩沖區,參數ab為審計緩沖區,參數fmt為格式化的字元串。其列出如下:void audit_log_format(struct audit_buffer *ab, const char *fmt, ...){va_list args;if (!ab)return;va_start(args, fmt);audit_log_vformat(ab, fmt, args);va_end(args);}函數audit_log_vformat將一個審計消息按格式寫入套接字緩沖區中,如果審計緩沖區沒有足夠的空間,就擴展套接字緩沖區的數據域。由於printk緩沖區為1024,擴展的套接字緩沖區最小應為1024。函數audit_log_vformat列出如下: static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args){int len, avail;struct sk_buff *skb;va_list args2;if (!ab)return;BUG_ON(!ab->skb);skb = ab->skb;avail = skb_tailroom(skb);//計算套接字緩沖區的空閑數據空間if (avail == 0) {//如果套接字緩沖區沒有空閑數據空間,擴展空間avail = audit_expand(ab, AUDIT_BUFSIZ);// AUDIT_BUFSIZ為1024,if (!avail)goto out;}va_(args2, args);len = vsnprintf(skb->tail, avail, fmt, args);//將信息寫入到緩沖區if (len >= avail) {//如果實際信息長度比可用的緩沖區大,擴展空間/* 由於printk緩沖區是1024,因此,擴展空間最少為1024 */avail = audit_expand(ab,max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));if (!avail)goto out;len = vsnprintf(skb->tail, avail, fmt, args2); //將審計信息寫入到緩沖區}if (len > 0)skb_put(skb, len); //將寫入信息的數據緩沖區附加到skb上out:return;}
函數audit_expand擴展在審計緩沖區中的套接字緩沖區,擴展成功,返回可用的空間大小,擴展失敗返回0,表示沒有空間。參數ab表示審計緩沖區的指針,參數extra表示加到套接字緩沖區skb尾部的緩沖區空間大小。函數audit_expand列出如下:static inline int audit_expand(struct audit_buffer *ab, int extra){struct sk_buff *skb = ab->skb;int ret = pskb_expand_head(skb, skb_headroom(skb), extra, ab->gfp_mask);if (ret < 0) {audit_log_lost("out of memory in audit_expand");return 0;}return skb_tailroom(skb);//返回可用的緩沖區空間大小}3.函數audit_log_end當進程完成了將審計記錄寫入審計緩沖區的操作時,它調用函數audit_log_end將套接字緩沖區中的審計記錄數據發送給用戶空間後台進程,由後台進程寫入到log文件。如果審計後台進程存在,使用netlink機制傳輸數據,由審計後台將套接字緩沖區中的審計記錄數據寫入審計文件audit.log中;如果審計後台不存在,使用函數printk記錄數據,然後由日誌後台進程將數據寫入到日誌文件中。當數據發送完成後,函數audit_log_end喚醒等待隊列kauditd_wait。有些進程因為審計套接字緩沖區鏈表上的緩沖區數量超過上限而在隊列kauditd_wait等待,當其他進程發送了數據時,應喚醒這些等待進程。函數audit_log_end列出如下:void audit_log_end(struct audit_buffer *ab){if (!ab)return;if (!audit_rate_check()) {//檢查審計系統的傳輸速度,如果netlink機制傳輸速度超過上限,則返回錯誤audit_log_lost("rate limit exceeded");} else {if (audit_pid) {//如果審計後台的進程ID存在,使用netlink機制傳輸數據struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);skb_queue_tail(&audit_skb_queue, ab->skb);ab->skb = NULL;wake_up_interruptible(&kauditd_wait);//發送了數據,喚醒等待隊列} else {//使用printk記錄數據printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0));}}audit_buffer_free(ab);}
❺ Linux下常用文本處理命令
Linux下常用文本處理命令大全
Linux下面有很多經典的非常有用的命令,其中處理文本的命令就有很多。下面就讓我們一起看看這些經典的Linux文本處理命令有哪些吧。
一. sort
文件排序, 通常用在管道中當過濾器來使用. 這個命令可以依據指定的關鍵字或指定的字元位置, 對文件行進行排序. 使用-m選項, 它將會合並預排序的輸入文件. 想了解這個命令的全部參數請參考這個命令的info頁.
二. tsort
拓撲排序, 讀取以空格分隔的有序對, 並且依靠輸入模式進行排序.
三. uniq
這個過濾器將會刪除一個已排序文件中的重復行. 這個命令經常出現在sort命令的管道後邊.
四. expand, unexpand
expand命令將會把每個tab轉化為一個空格. 這個命令經常用在管道中.
unexpand命令將會把每個空格轉化為一個tab. 效果與expand命令相反.
五. cut
一個從文件中提取特定域的工具. 這個命令與awk中使用的print $N命令很相似, 但是更受限. 在腳本中使用cut命令會比使用awk命令來得容易一些. 最重要的選項就是-d(欄位定界符)和-f(域分隔符)選項.
六. paste
將多個文件, 以每個文件一列的形式合並到一個文件中, 合並後文件中的每一列就是原來的一個文件. 與cut結合使用, 經常用於創建系統log文件.
七. join
這個命令與paste命令屬於同類命令. 但是它能夠完成某些特殊的目地. 這個強力工具能夠以一種特殊的形式來合並兩個文件, 這種特殊的形式本質上就是一個關聯資料庫的簡單版本.
join命令只能夠操作兩個文件. 它可以將那些具有特定標記域(通常是一個數字標簽)的行合並起來, 並且將結果輸出到stdout. 被加入的文件應該事先根據標記域進行排序以便於能夠正確的匹配.
八. head
把文件的頭部內容列印到stdout上(默認為10行, 可以自己修改). 這個命令有一些比較有趣的選項.
九. tail
將一個文件結尾部分的內容輸出到stdout中(默認為10行). 通常用來跟蹤一個系統logfile的.修改情況, 如果使用-f選項的話, 這個命令將會繼續顯示添加到文件中的行.
十. wc
wc可以統計文件或I/O流中的”單詞數量”:
十一. fold
將輸入按照指定寬度進行折行. 這里有一個非常有用的選項-s, 這個選項可以使用空格進行斷行(譯者: 事實上只有外文才需要使用空格斷行, 中文是不需要的)(請參考例子 12-23和例子 A-1).
十二. fmt
一個簡單的文件格式器, 通常用在管道中, 將一個比較長的文本行輸出進行”折行”.
十三. col
這個命令用來濾除標准輸入的反向換行符號. 這個工具還可以將空白用等價的tab來替換. col工具最主要的應用還是從特定的文本處理工具中過濾輸出, 比如groff和tbl. (譯者: 主要用來將man頁轉化為文本.)
十四. column
列格式化工具. 通過在合適的位置插入tab, 這個過濾工具會將列類型的文本轉化為”易於列印”的表格式進行輸出.
十五. colrm
列刪除過濾器. 這個工具將會從文件中刪除指定的列(列中的字元串)並且寫到文件中, 如果指定的列不存在, 那麼就回到stdout. colrm 2 4 <filename將會刪除filename文件中每行的第2到第4列之間的所有字元. p=""> </filename將會刪除filename文件中每行的第2到第4列之間的所有字元.>
Caution: 如果這個文件包含tab和不可列印字元, 那將會引起不可預期的行為. 在這種情況下, 應該通過管道的手段使用expand和unexpand來預處理colrm.
十六. nl
計算行號過濾器. nl filename將會把filename文件的所有內容都輸出到stdout上, 但是會在每個非空行的前面加上連續的行號. 如果沒有filename參數, 那麼就操作stdin.
nl命令的輸出與cat -n非常相似, 然而, 默認情況下nl不會列出空行.
十七. pr
格式化列印過濾器. 這個命令會將文件(或stdout)分頁, 將它們分成合適的小塊以便於硬拷貝列印或者在屏幕上瀏覽. 使用這個命令的不同的參數可以完成好多任務, 比如對行和列的操作, 加入行, 設置頁邊, 計算行號, 添加頁眉, 合並文件等等. pr命令集合了許多命令的功能, 比如nl, paste, fold, column, 和expand.
pr -o 5 –width=65 fileZZZ | more 這個命令對fileZZZ進行了比較好的分頁, 並且列印到屏幕上. 文件的縮進被設置為5, 總寬度設置為65.
一個非常有用的選項-d, 強制隔行列印(與sed -G效果相同).
十八. gettext
GNU gettext包是專門用來將程序的輸出翻譯或者本地化為不同國家語言的工具集. 在最開始的時候僅僅支持C語言, 現在已經支持了相當數量的其它程序語言和腳本語言.
想要查看gettext程序如何在shell腳本中使用. 請參考info頁.
十九. msgfmt
一個產生二進制消息目錄的程序. 這個命令主要用來本地化.
二十. iconv
一個可以將文件轉化為不同編碼格式(字元集)的工具. 這個命令主要用來本地化.
二十一. recode
可以認為這個命令是上邊iconv命令的專業版本. 這個非常靈活的並可以把整個文件都轉換為不同編碼格式的工具並不是Linux標准安裝的一部分.
二十二. TeX, gs
TeX和Postscript都是文本標記語言, 用來對列印和格式化的視頻顯示進行預拷貝.
TeX是Donald Knuth精心製作的排版系統. 通常情況下, 通過編寫腳本的手段來把所有的選項和參數封裝起來一起傳到標記語言中是一件很方便的事情.