2013-04-04 46 views
71

bất cứ ai có thể giải thích cho tôi,điều khiển thiết bị Linux IOCTL

  1. IOCTL là gì?
  2. Nó được sử dụng để làm gì?
  3. Tôi làm cách nào để sử dụng?
  4. Tại sao tôi không thể xác định chức năng mới thực hiện công việc giống như IOCTL?

Trả lời

59

An ioctl, có nghĩa là "kiểm soát đầu vào-đầu ra" là một loại cuộc gọi hệ thống cụ thể cho từng thiết bị. Chỉ có một vài cuộc gọi hệ thống trong Linux (300-400), mà không đủ để thể hiện tất cả các thiết bị chức năng độc đáo có thể có. Vì vậy, một trình điều khiển có thể xác định một ioctl cho phép một ứng dụng không gian người dùng gửi các đơn đặt hàng đó. Tuy nhiên, ioctls không phải là rất linh hoạt và có xu hướng lộn xộn một chút (hàng chục "số ma thuật" chỉ hoạt động ... hoặc không), và cũng có thể không an toàn, khi bạn chuyển bộ đệm vào hạt nhân - việc xử lý không đúng có thể phá vỡ mọi thứ dễ dàng.

Phương án thay thế là giao diện sysfs, nơi bạn thiết lập tệp dưới /sys/ và đọc/ghi để nhận thông tin từ và đến trình điều khiển. Một ví dụ về làm thế nào để thiết lập:

static ssize_t mydrvr_version_show(struct device *dev, 
     struct device_attribute *attr, char *buf) 
{ 
    return sprintf(buf, "%s\n", DRIVER_RELEASE); 
} 

static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL); 

Và trong khi cài đặt driver:

device_create_file(dev, &dev_attr_version); 

Sau đó, bạn sẽ có một tập tin cho thiết bị của bạn trong /sys/, ví dụ, /sys/block/myblk/version cho một trình điều khiển khối.

Phương pháp khác để sử dụng nặng hơn là liên kết mạng, là phương pháp IPC (liên lạc liên ngành) để nói chuyện với người lái xe của bạn qua giao diện ổ cắm BSD. Điều này được sử dụng, ví dụ, bởi các trình điều khiển WiFi. Sau đó, bạn giao tiếp với nó từ không gian người dùng bằng cách sử dụng thư viện libnl hoặc libnl3.

+0

Câu trả lời này 'trả lời' câu hỏi một phần. –

100

ioctl chức năng hữu ích khi một người đang triển khai trình điều khiển thiết bị để đặt cấu hình trên thiết bị. ví dụ. một máy in có các tùy chọn cấu hình để kiểm tra và thiết lập phông chữ, cỡ chữ, vv .. ioctl có thể được sử dụng để lấy phông chữ hiện tại cũng như đặt phông chữ cho phông chữ khác. Trong ứng dụng của người dùng, hãy sử dụng ioctl để gửi mã tới máy in yêu cầu mã trả về phông chữ hiện tại hoặc đặt phông chữ thành phông chữ mới.

int ioctl(int fd, int request, ...) 
  1. fd là mô tả tập tin, là trả về bởi mở
  2. request là yêu cầu mã. Ví dụ: GETFONT sẽ nhận phông chữ hiện tại từ máy in, SETFONT sẽ đặt phông chữ trên máy in.
  3. đối số thứ ba là void *. Tùy thuộc vào đối số thứ hai, thứ ba có thể có hoặc không có mặt. ví dụ: nếu đối số thứ hai là SETFONT, đối số thứ ba có thể cung cấp tên phông chữ là ARIAL.

Hiện tại, yêu cầu int không chỉ là macro, yêu cầu tạo mã yêu cầu để sử dụng ứng dụng người dùng và mô-đun trình điều khiển thiết bị để xác định cấu hình trên thiết bị. Một gửi mã yêu cầu bằng cách sử dụng ioctl từ ứng dụng người dùng và sau đó sử dụng mã yêu cầu trong mô-đun trình điều khiển thiết bị để xác định hành động cần thực hiện.

Một mã yêu cầu có 4 phần chính

1. A Magic number - 8 bits 
    2. A sequence number - 8 bits 
    3. Argument type (typically 14 bits), if any. 
    4. Direction of data transfer (2 bits). 

Nếu yêu cầu code đang SETFONT để thiết lập font chữ trên máy in, phương pháp truyền dữ liệu sẽ được từ người sử dụng ứng dụng để mô-đun điều khiển thiết bị. Người dùng gửi tên phông chữ Arial đến máy in. Nếu mã yêu cầu là GETFONT, hướng từ máy in đến ứng dụng của người dùng.

Để tạo mã yêu cầu, Linux cung cấp một số chức năng được xác định trước như macro.

1. _IO(MAGIC, SEQ_NO) cả hai đều là 8 bit, 0 đến 255, ví dụ: chúng ta hãy nói rằng chúng ta muốn tạm dừng máy in. Điều này không yêu cầu chuyển dữ liệu. Vì vậy, chúng ta sẽ tạo ra mã yêu cầu như sau

#define PRIN_MAGIC 'P' 
    #define NUM 0 
    #define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

Bây giờ sử dụng ioctl như

ret_val = ioctl(fd, PAUSE_PRIN); 

tương ứng gọi hệ thống trong mô-đun điều khiển sẽ nhận được mã và tạm dừng các máy in.

  1. __IOW(MAGIC, SEQ_NO, TYPE)MAGICSEQ_NO là tương tự như trên, nhưng phần thứ ba cung cấp cho các loại lập luận tiếp theo, nhớ lại số thứ ba của ioctlvoid *. W trong __IOW cho biết hướng dữ liệu từ ứng dụng người dùng đến mô-đun trình điều khiển. Chúng ta hãy lấy một ví dụ, Giả sử người ta đang yêu cầu máy in đặt phông chữ thành Arial.

    #define PRIN_MAGIC 'S' 
    #define SEQ_NO 1 
    #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long) 
    

hơn nữa,

char *font = "Arial"; 
    ret_val = ioctl(fd, SETFONT, font); 

Bây giờ font là một con trỏ, có nghĩa là nó là một địa chỉ đại diện tốt nhất như unsigned long, do đó phần thứ ba của _IOW đề cập đến loại như vậy. Ngoài ra, địa chỉ phông chữ này được truyền cho cuộc gọi hệ thống tương ứng được thực hiện trong mô-đun trình điều khiển thiết bị là unsigned long và chúng tôi cần truyền đến đúng loại trước khi sử dụng. Không gian hạt nhân có thể truy cập vào không gian người dùng và do đó nó hoạt động. hai hàm khác như macro là __IOR(MAGIC, SEQ_NO, TYPE)__IORW(MAGIC, SEQ_NO, TYPE) nơi hướng luồng dữ liệu sẽ từ không gian hạt nhân đến không gian người dùng và cả hai cách tương ứng.

Vui lòng cho tôi biết nếu điều này có ích!

+0

Tôi tự hỏi, nếu các hàm __IOW, __IOR và __IORW ở trên là đúng (tôi có nghĩa là dấu gạch dưới kép trong một số trường hợp, trong một số trường hợp không. Tôi chưa bao giờ sử dụng dấu gạch dưới kép) ... Cảm ơn bạn đã giải thích rõ ràng! – jcoppens

Các vấn đề liên quan