2012-02-13 30 views
3

我有一個64位的企業單位的SuSE 11 我有打開HIDRAW設備並在其上運行的ioctl函數來得到這種設備的原始信息象下面這樣的應用程序:關於執行ioctl函數,在32位模式下編譯和在64位os上編譯64位模式有什麼不同?

struct hidraw_devinfo devinfo; 
int fd = open("/dev/hidraw0", 0); 
int ret = ioctl(fd, HIDIOCGRAWINFO, &devinfo); 
... 

如果我編譯這個程序中64位模式沒有錯誤,沒有問題,當我執行應用程序時,ioctl函數可以正常工作。

g++ main.cpp 

如果我在32位模式下編譯這個程序,也沒有錯誤,也沒有問題。但是當我執行應用程序的ioctl函數返回EINVAL錯誤(錯誤= 22,參數無效)

g++ -m32 main.cpp 

什麼問題?

注:

struct hidraw_devinfo 
{ 
    __u32 bustype; 
    __s16 vendor; 
    __s16 product; 
} 

回答

3

Linux ioctl定義和兼容性層是一個引人入勝的話題,我剛剛撞見了我的頭。

通常ioctl定義使用一個系列的宏_IOW/_IOR等人即把你的參數類型名字作爲參考,有一個神奇的數字和順序值是被改寫的,給你你的IOCTL參數值一起(如HIDIOCGRAWINFO) 。類型名稱用於將sizeof(arg_type)編碼到定義中。這意味着在用戶空間中使用的類型決定了由ioctl宏生成的 - 即HIDIOCGRAWINFO可能會因包含條件而異。

這裏是第一點,其中32位和64位不同,sizeof可能會有所不同,取決於打包,使用模糊的數據大小(如長),​​但特別是(和不可避免的),如果您使用指針參數。因此,在這種情況下,需要支持32位客戶端的64位內核模塊需要定義兼容性參數類型以匹配參數類型的32位等效版本的佈局,從而與32位兼容的ioctl匹配。這些32位等效定義使用稱爲compat的內核設施/層。

在你的情況下,sizeof()是相同的,所以這不是你正在採取的路徑 - 但它是重要的瞭解可能發生的一切。

此外,內核配置可能會定義CONFIG_COMPAT,它會更改sys-call包裝器(特別是圍繞用戶/內核接口的代碼)以減輕支持32位和64位的負擔。其中一部分包括兼容性ioctl的回調稱爲ioctl_compat

我所看到的是CONFIG_COMPAT定義的32位程序將生成代碼,提供ioctl S到ioctl_compat回調,即使64位確實可以產生相同的ioctl值(例如,在你的案件)。所以驅動程序編寫者需要確保ioctl_compat處理兩個特殊(不同)32位兼容ioctl類型和正常的「64位或不變的32位」類型。

因此,僅在32位和64位系統(無CONFIG_COMPAT)上設計和測試的內核模塊可能適用於32位和64位程序,但不適用於支持這兩種方法的程序。

所以在尋找HID我看到這是在2.6.38補充說:

http://lxr.linux.no/#linux+v2.6.38/drivers/hid/hidraw.c#L347

+0

和:http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=commit;h=ae5e49c79c051ea1d5ca91cbd4a0d22189067ba3 – Greg 2012-03-27 04:36:49

3

的問題可能是devinfo結構程序傳遞給ioctl功能之間的不匹配。

我猜你在64位系統上的工作。因此,您的內核以64位運行,而您與之通話的內核模塊(與ioctl)也是64位。

當您以64位編譯用戶程序時,內核模塊和用戶程序中的devinfo定義是相同的。

當您以32位編譯用戶程序時,內核模塊中的devinfo定義與您在用戶程序中的定義不同。事實上,在32位中,某些類型的大小發生了變化:主要是long和指針。因此,您的程序會創建一定大小的結構,並且內核模塊會以不同的方式解釋它所接收的數據。內核模塊可能不理解你給它的值,因爲它不會在你放置它的位置上查找它。

解決的方法是注意devinfo結構的定義,以便在編譯32位和64位時具有相同的二進制表示形式。

+1

我無法理解你的答案。 __u32在32位和64位都是4個字節。 以及__s16在32位和64位都是2個字節。 和sizeof(hidraw_devinfo)的長度是8個字節(考慮操作系統打包)。 – 2012-02-13 12:54:11

+0

另一種解釋是內核模塊不希望32位用戶程序調用它。 (必須有一些特殊的東西來接受它們。)但是,如果是這種情況,我會驚訝於'-EINVAL'錯誤。 – 2012-02-13 16:20:25