5

Hiện tại, tôi đang học trình điều khiển thiết bị Linux. Và đã bị mắc kẹt về cách mở một tập tin thiết bị hoạt động?cách hoạt động của các trình điều khiển thiết bị và tệp thông thường

Những gì tôi đã cho đến bây giờ ... Hãy xem xét một mã đơn giản mở ra một file bình thường ..

#incldue<stdio.h> 
int main() { 
    FILE fp; 
    char buffer[20]; 
    fp = fopen(/home/yoggi/foo.txt, "r"); 
    fread(buffer, 5, 1, fp); 
} 

Trong chương trình trên, The fopen(), chức năng c-thư viện, là một chức năng wrapper vào hệ thống, hãy gọi mở(), thực tập viên gọi sys_open() hoặc file_open() trong lớp VFS. Vì linux hỗ trợ một số hệ thống tệp, hệ thống tệp ảo sau đó chuyển điều khiển sang bộ xử lý tệp thực tế để mở tệp đó.

1) How does virtual file system(VFS) get to know on which file system the 
    underline file resides? 
2) How does it then calls the file_open or open function of that particular 
    filesystem to open file. 

Trong trường hợp các trình điều khiển thiết bị tương tự xảy ra. Giả sử một trình điều khiển thiết bị đơn giản.

#include <linux/module.h> 
// othher includes... 
static dev_t first; // Global variable for the first device number 
static struct cdev c_dev; // Global variable for the character device structure 
static struct class *cl; // Global variable for the device class 
static int my_open(struct inode *i, struct file *f) 
{ 
    printk(KERN_INFO "Driver: open()\n"); 
    return 0; 
} 
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) 
{ 
    printk(KERN_INFO "Driver: read()\n"); 
    return 0; 
} 
struct file_operations pugs_fops = 
{ 
.owner = THIS_MODULE, 
.open = my_open, 
.read = my_read, 
}; 

static int __init ofcd_init(void) /* Constructor */ 
{ 
    printk(KERN_INFO "Namaskar: ofcd registered"); 
    if (alloc_chrdev_region(&first, 0, 1, "Shweta") < 0) 
    { 
    return -1; 
    } 
    if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL) 
    { 
    unregister_chrdev_region(first, 1); 
    return -1; 
} 
if (device_create(cl, NULL, first, NULL, "mynull") == NULL) 
{ 
    class_destroy(cl); 
    unregister_chrdev_region(first, 1); 
    return -1; 
} 
    cdev_init(&c_dev, &pugs_fops); 
if (cdev_add(&c_dev, first, 1) == -1) 
{ 
    device_destroy(cl, first); 
    class_destroy(cl); 
    unregister_chrdev_region(first, 1); 
    return -1; 
} 
    return 0; 
} 

static void __exit ofcd_exit(void) /* Destructor */ 
{ 
cdev_del(&c_dev); 
device_destroy(cl, first); 
class_destroy(cl); 
unregister_chrdev_region(first, 1); 
printk(KERN_INFO "Alvida: ofcd unregistered"); 
} 
module_init(ofcd_init); 
module_exit(ofcd_exit); 
MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>"); 
MODULE_DESCRIPTION("Our First Character Driver"); 

Trước hết, chúng tôi phân bổ các số nhỏ chính cho thiết bị. Đăng ký cho phạm vi của các tập tin thiết bị và Liên kết các hoạt động tập tin thiết bị với các chức năng của trình điều khiển thiết bị.

Một số thuật ngữ tôi đã không nhận được ..

1) What does actually cdev_add() do? in terms of registering a device to the 
    kernel. 
2) Registering a device to the kernel means? 
3) How does a open(/dev/mynull, O_RONLY); called on a device file actually calls 
    the open function of driver which is mapped while initializing the device 
    by calling routine cdev_init(&c_dev, &pugs_fops); ? 

Trả lời

7

1) Làm thế nào để hệ thống tập tin ảo (VFS) tìm hiểu về hệ thống tập tin mà các tập tin gạch dưới cư trú?

Bạn cần phải xác định tập tin bạn đang cố gắng để mở bởi đầy đủ tên đường dẫn của nó (hoặc thư mục làm việc hiện tại ).
Vì vậy, bằng cách duyệt qua đường dẫn thư mục này ngược, kết quả đầu tiên (đường dẫn sâu nhất) đến điểm gắn kết sẽ cung cấp hệ thống tệp được gắn, loại hệ thống tệp và thiết bị.

Mỗi hệ thống tệp cung cấp thông tin này khi được gắn và được lưu trong bảng gắn kết.
Bạn có thể xem thông tin này (trạng thái hiện tại) bằng cách sử dụng lệnh mount.

2) Làm thế nào để nó gọi hàm file_open hoặc mở của hệ thống tệp cụ thể đó để mở tệp.

Một khi hệ thống tập tin được biết, các ops cấu trúc cho rằng FS được lấy ra, và entrypoint open() có thể được gọi.

1) Điều gì thực sự cdev_add() làm gì? về việc đăng ký thiết bị với hạt nhân .

Đăng ký trình điều khiển (ví dụ: cdev_init() cho thiết bị char) cài đặt cấu trúc ops của trình điều khiển liệt kê các điểm nhập của các chức năng mà người lái xe có thể thực hiện.
cdev_add() thông báo cho hạt nhân rằng trình điều khiển có thể kiểm soát một trường hợp cụ thể của loại thiết bị char đó.Cá thể thiết bị đó được gán một số nhỏ liên kết tên thiết bị trong /dev để thông tin trạng thái trong trình điều khiển.
Lưu ý rằng các loại thiết bị không phải là char (các thiết bị mạng hoặc nền tảng (bus)) thuộc về một hệ thống phụ khác nhau và sử dụng các thủ tục đăng ký khác nhau.

2) Đăng ký thiết bị với hạt nhân nghĩa là gì?

Quyền truy cập vào thiết bị đó hiện đã được bật.

3) Cách mở (/ dev/mynull, O_RONLY); gọi trên một tập tin thiết bị thực sự gọi chức năng mở của trình điều khiển được ánh xạ trong khi khởi tạo thiết bị bằng cách gọi thường lệ cdev_init (& c_dev, & pugs_fops); ?

Trình điều khiển init() thường chỉ nên được gọi một lần khi tài xế được tải. Thói quen này nên thăm dò sự tồn tại và trạng thái hoạt động của tất cả các trường hợp của thiết bị. Các tài nguyên như các đường ngắt, các kênh DMA và cổng I/O và/hoặc không gian bộ nhớ sẽ được thu nhận. Trình điều khiển đăng ký cấu trúc ops của nó với hạt nhân. Trình điều khiển đăng ký từng cá thể của thiết bị bằng hạt nhân.

Cuộc gọi open() trong không gian người dùng được xử lý bởi thư viện C. Tên thiết bị /dev được dịch sang số chính của thiết bị (xác định hệ thống con hoặc thiết bị nào, ví dụ: tty hoặc âm thanh, phải xử lý yêu cầu) và số phụ (xác định trình điều khiển thiết bị nào sử dụng và phiên bản nào của thiết bị được truy cập). Bộ vi xử lý được chuyển sang chế độ giám sát để có thể gọi thường trình open() của trình điều khiển hạt nhân, được lấy ra từ cấu trúc ops của trình điều khiển. Để biết thêm một chút về cấu trúc ops, hãy xem điều này other answer.