一: ioctl函數的作用
ioctl用于向裝置發控制和配置指令 ,有些指令也需要讀寫一些資料,但這些資料是不能用read/write讀寫的,稱為Out-of-band資料。也就是說,read/write讀寫的資料是in-band資料,是I/O操作的主體,而ioctl指令傳送的是控制資訊 ,其中的資料是輔助的資料。
ioctl是裝置驅動程式中對裝置的I/O通道進行管理的函數,所謂對I/O通道進行管理,就是對裝置的一些特性進行控制 ,例如,在序列槽線上收發資料通過read/write操作,而序列槽的波特率、校驗位、停止位通過ioctl設定,A/D轉換的結果通過read讀取,而A/D轉換的精度和工作頻率通過ioctl設定。
ioctl函數是檔案結構中的一個屬性分量,就是說如果你的驅動程式提供了對ioctl的支援,使用者就可以在使用者程式中使用ioctl函數控制裝置的I/O通道。
如果不用ioctl的話,也可以實作對裝置I/O通道的控制,但那就是蠻擰了。例如,我們可以在驅動程式中實作write的時候檢查一下是否有特殊約定的資料流通過,如果有的話,那麼後面就跟着控制指令(一般在socket程式設計中常常這樣做)。但是如果這樣做的話,會導緻代碼分工不明,程式結構混亂,程式員自己也會頭昏眼花的。
是以,我們就使用ioctl來實作控制的功能 。要記住,使用者程式所作的隻是通過指令碼告訴驅動程式它想做什麼,至于怎麼解釋這些指令和怎麼實作這些指令,這都是驅動程式要做的事情。
二: ioctl()用法
int ioctl(int fd, ind cmd, …);
其中fd就是使用者程式打開裝置時使用open函數傳回的檔案标示符,cmd就是使用者程式對裝置的控制指令,至于後面的省略号,那是一些補充參數,一般最多一個,有或沒有是和cmd的意義相關的。下面是一個關于V4L視訊采集中用到的用ioctl來配置視訊采集裝置(USB攝像頭)的一些特性參數的例子:
1. 定義裝置結構體
struct vdIn {
int fd ; //裝置描述符
char *videodevice ; //裝置節點,在linux下,通用的視訊采集裝置節點為/dev/video0
struct video_mmap vmmap;
struct video_capability videocap;
int mmapsize;
struct video_mbuf videombuf;
struct video_picture videopict;
struct video_window videowin;
struct video_channel videochan;
int cameratype ;
char *cameraname;
char bridge[9];
int sizenative; // available size in jpeg
int sizeothers; // others palette
int palette; // available palette
int norme ; // set spca506 usb video grabber
int channel ; // set spca506 usb video grabber
int grabMethod ;
unsigned char *pFramebuffer;
unsigned char *ptframe[4];
int framelock[4];
pthread_mutex_t grabmutex;
int framesizeIn ;
volatile int frame_cour;
int bppIn;
int hdrwidth;
int hdrheight;
int formatIn;
int signalquit;
};
2. 裝置節點指派, "/dev/video0"是真實的實體攝像頭裝置在linux中的表示
if (videodevice == NULL || *videodevice == 0)
{
videodevice = "/dev/video0";
}
3. 調用 裝置 初始化函數
struct vdIn videoIn; //在spcav4l.h中定義
videodevice = "/dev/video0"; //節點
int width = 352; //寬
int height = 288; //高
int format = VIDEO_PALETTE_JPEG; //格式
int grabmethod = 1;
memset (&videoIn, 0, sizeof (struct vdIn));
if (init_videoIn(&videoIn, videodevice, width, height, format,grabmethod) != 0)
if(debug) printf (" damned encore rate !!/n");
4. 裝置初始化函數傳值
int init_videoIn (struct vdIn *vd, char *device, int width, int height,
int format, int grabmethod)
{
int err = -1;
int i;
if (vd == NULL || device == NULL)
return -1;
if (width == 0 || height == 0)
return -1;
if(grabmethod < 0 || grabmethod > 1)
grabmethod = 1; //read by default;
// check format
vd->videodevice = NULL;
vd->cameraname = NULL;
vd->videodevice = NULL;
vd->videodevice = (char *) realloc (vd->videodevice, 16);
vd->cameraname = (char *) realloc (vd->cameraname, 32);
snprintf (vd->videodevice, 12, "%s", device);
if(debug) printf("video %s /n",vd->videodevice);
memset (vd->cameraname, 0, sizeof (vd->cameraname));
memset(vd->bridge, 0, sizeof(vd->bridge));
vd->signalquit = 1;//信号設定
vd->hdrwidth = width;
vd->hdrheight = height;
vd->formatIn = format; //傳進來的 format = VIDEO_PALETTE_JPEG;
vd->bppIn = GetDepth (vd->formatIn);
vd->grabMethod = grabmethod; //mmap or read
vd->pFramebuffer = NULL;
err = init_v4l (vd); // V4L初始化函數
....................................................
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5COxMWM1MGMkZDOlhzNjFzYwYjMkFTO1kDM3EzMzEjYw8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)