【問題排查】error: too many arguments to function ‘tty->driver->ops->ioctl‘處理
阿新 • • 發佈:2021-01-28
技術標籤:Linux 日常使用與開發系統報錯及處理ttyioctllinux核心嵌入式
當前核心版本:3.18.y
原始碼對應的核心版本:2.6.37
程式碼移植過程中報錯:
...491:13: error: too many arguments to function 'tty->driver->ops->ioctl'
error = (tty->driver->ops->ioctl)(tty, file, FIONWBUFD, (unsigned long)&d_buff);
比較兩個核心的差異。
tty->driver->ops->ioctl 最終找到差異點: 【3.18.y】 struct tty_operations { ... int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); } 【2.6.37】 struct tty_operations { ... int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); }
解決辦法就是去掉一個file引數就行了。
為什麼會有差異?為什麼去掉了struct file引數?
struct file * file:ioctl的操作有可能是要修改檔案的屬性,或者訪問硬體。要修改檔案屬性的話,就要用到這個結構體了,所以這裡傳來了它們的指標
順便發一下,tty_operations各個成員的作用:
struct tty_operations { struct tty_struct * (*lookup)(struct tty_driver *driver, struct inode *inode, int idx); //返回對應的tty裝置, 若為NULL則返回ERR_PTR, 在tty_mutex函式中呼叫 int (*install)(struct tty_driver *driver, struct tty_struct *tty); //install一個tty裝置到tty驅動的內部表,與lookup和remove法相關聯 void (*remove)(struct tty_driver *driver, struct tty_struct *tty); //從tty驅動的內部表,remove一個關閉了的tty裝置,與lookup和remove法相關聯 int (*open)(struct tty_struct * tty, struct file * filp); //當一個特別的tty裝置open的時候,將呼叫該例程;該例程是強制性的,若該例程沒有加入operations,open tty的時候將返回ENODEV //必須使用的方法 void (*close)(struct tty_struct * tty, struct file * filp); //當tty裝置關閉時呼叫 //必須使用的方法 void (*shutdown)(struct tty_struct *tty); //在tty在關閉時,若仍持有一個帶鎖的特殊裝置,需要呼叫該例程,想想我們經常使用的sudo shutdown -r/h/... now就明白了 //它執行在tty裝置釋放資源之前,所以可能執行在另一個tty裝置持有kref的時候 void (*cleanup)(struct tty_struct *tty); //當一個tty裝置在最後一次被關閉和釋放資源時,非同步地呼叫該例程,這個例程可以看成shutdown的可休眠的第二部分 int (*write)(struct tty_struct * tty, const unsigned char *buf, int count); //寫函式,不多說 //可選使用:在需要寫的裝置中 int (*put_char)(struct tty_struct *tty, unsigned char ch); //當核心想寫單個字元到tty裝置時,呼叫該例程(其實也可以呼叫write例程,呼叫時置count為1即可) //可選使用:若裝置在呼叫時未提供將使用write法 //注意:不要直接呼叫該例程,而應呼叫tty_put_char void (*flush_chars)(struct tty_struct *tty); //這個例程呼叫在tty使用put_char輸出很多個字元後 //可選 //注意:不要直接呼叫,呼叫tty_driver_flush_chars int (*write_room)(struct tty_struct *tty); //這個例程返回tty裝置將被寫入的字元佇列長度 //這個數字受輸出緩衝區和輸出流的變化影響 //當有write函式時需要 //注意:不要直接呼叫,呼叫tty_write_room int (*chars_in_buffer)(struct tty_struct *tty); //在buffer區中的字元 int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); //該例程允許tty裝置實施裝置特殊的ioctl,若ioctl的數值在cmd中未被裝置檢測到,將返回ENOIOCTLCMD //可選 long (*compat_ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); //在64位系統中執行32位的ioctl的例程 //可選 void (*set_termios)(struct tty_struct *tty, struct ktermios * old); //該例程在裝置的termios設定改變時通知驅動 //可選:在持termios lock的時候呼叫 void (*throttle)(struct tty_struct * tty); //當執行緒規劃快滿的時候提醒驅動程式,提示不要再輸入字元到tty中 //可選:通常在tty_throttle()函式中獲得termios lock時呼叫 void (*unthrottle)(struct tty_struct * tty); //提醒驅動程式,可以輸入字元到tty中,因為執行緒規劃空間夠用 //可選:通常在tty_unthrottle()函式中,獲得termios lock時呼叫 void (*stop)(struct tty_struct *tty); //提醒驅動,停止輸出字元 //可選,注意:不是呼叫stop_tty void (*start)(struct tty_struct *tty); //提醒驅動,接著輸入字元 //可選,助於:不是呼叫start_tty void (*hangup)(struct tty_struct *tty); //掛起tty,可選 int (*break_ctl)(struct tty_struct *tty, int state); //開啟或關閉RS-232口,state為-1則開啟,state為0則關閉 //若該函式執行,則高一級的tty將處理四種ioctls:TCSBRK, TCSBRKP, TIOCSBRK, TIOCCBRK //如果驅動程式設定了TTY_DRIVER_HARDWARE_BREAK,接著介面將被稱作實際時間,而硬體延遲工作 //可選:需要收到TCSBRK/BRKP/etc void (*flush_buffer)(struct tty_struct *tty); //在使用put_char()寫入一串字元後,該函式被核心呼叫 //可選 //注意:呼叫是應為tty_driver_flush_buffer void (*set_ldisc)(struct tty_struct *tty); //該例程在裝置的termios設定改變時通知驅動 //可選:有BKL (currently)時呼叫 void (*wait_until_sent)(struct tty_struct *tty, int timeout); //該例程等待裝置將其所有字元寫入傳輸FIFO中 //可選:若裝置有FIFO則需要 //注意:通常使用為tty_wait_until_sent void (*send_xchar)(struct tty_struct *tty, char ch); //該例程傳送一個大端的XON/XOFF給驅動程式 //可選:如果不提供,之後寫函式將被原子鎖呼叫來保持它的序列性 int (*tiocmget)(struct tty_struct *tty); //獲得tty的線路設定 int (*tiocmset)(struct tty_struct *tty, unsigned int set, unsigned int clear); //設定tty的線路設定 int (*resize)(struct tty_struct *tty, struct winsize *ws); //當一個termios的請求將改變 請求終端幾何(requested terminal geometry)時呼叫 //可選:預設行為是 無錯誤地更新termios structure...... int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); //當收到一個termiox基於ioctl的訊號時呼叫,將使用者空間的請求向下傳遞 //這個函式只有當tty包含tty->termiox指標的時候才會執行 //可選:持有termios lock的時候呼叫 int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount); //當裝置收到一個TIOCGICOUNT的訊號時呼叫,將一個核心結構傳入使其完成。 //這個函式只有在提供的時候呼叫,否則將返回EINVAL #ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); void (*poll_put_char)(struct tty_driver *driver, int line, char ch); #endif const struct file_operations *proc_fops; };