2012-06-25 23 views
6

Tôi có trình điều khiển thiết bị nhân vật Linux tạo mục nhập /dev/mything và sau đó là chương trình C++/Qt mở thiết bị và sử dụng thiết bị. Nếu chương trình đó thoát đúng cách, với exit(), thiết bị sẽ đóng và trình điều khiển sẽ tự đặt lại chính xác. Nhưng nếu chương trình thoát bất thường, thông qua segfault hoặc SIGINT hoặc một cái gì đó, thiết bị không được đóng đúng cách.Trình điều khiển thiết bị nhân vật Linux có thể phát hiện ra như thế nào khi chương trình sử dụng nó thoát bất thường?

Giải pháp hiện tại của tôi là tải lại trình điều khiển nếu nó bị kẹt trong trạng thái "mở".

dòng trong trình điều khiển này sẽ cố gắng để ngăn chặn nhiều chương trình sử dụng các thiết bị cùng một lúc:

int mything_open(struct inode* inode, struct file* filp) { 
    ... 
    if (port->rings[bufcount].virt_addr) return -EBUSY; 
    ... 
} 

Sau đó này làm sạch nó lên:

int mything_release(struct inode* inode, struct file* filp) { 
    ... 
    port->rings[bufcount].virt_addr = NULL; 
    ... 
} 

Tôi nghĩ exit() đang gây ra mything_release được gọi nhưng SIGINT không phải là. Làm thế nào tôi có thể làm cho người lái xe mạnh mẽ hơn đối với loại tình huống này?

EDIT:

Dưới đây là các hoạt động tôi đã triển khai. Có lẽ tôi đang thiếu một cái gì đó?

static struct file_operations fatpipe_fops = { 
    .owner = THIS_MODULE, 
    .open =  mything_open, 
    .release = mything_release, 
    .read =  mything_read, 
    .write = mything_write, 
    .ioctl = mything_ioctl 
}; 
+2

Khi các proces thoát hoặc bị chấm dứt, hạt nhân sẽ giải phóng tài nguyên. Bao gồm số lượng tham chiếu trên bất kỳ phần mô tả tệp mở nào. – wildplasser

+0

Nếu đó là trường hợp, tại sao sau khi chương trình của tôi chấm dứt với SIGINT/segfault, tôi nhận được 'Thiết bị hoặc tài nguyên bận 'khi tôi cố gắng mở lại chương trình? Tôi không thấy lỗi đó nếu tôi thoát khỏi nó một cách sạch sẽ và mở lại nó. – Dave

+0

Tôi không biết mã của bạn. Có lẽ bạn có giá trị sai cho bufcount? Có lẽ bạn đã không thực hiện một trong những chức năng cần thiết? – wildplasser

Trả lời

1

Vấn đề luộc xuống dòng này trong mything_release, đưa vào để chờ đợi đối với một số bộ nhớ viết để hoàn thành:

if (wait_event_interruptible_timeout(port->inq, false, 10)) return -ERESTARTSYS; 

Với một lối ra chương trình bình thường, điều này sẽ quay trong vòng 10 jiffies và tiếp tục cùng. Nhưng với một lối ra bất thường từ SIGINT hoặc một cái gì đó, tôi nghĩ rằng thời gian chờ gián đoạn đã bị gián đoạn và nó trở về -ERESTARTSYS, gây ra nếu tôi trả lại như cũ.

Điều mà làm việc cho tôi là chỉ cần thoát khỏi if và chỉ chờ:

wait_event_interruptible_timeout(port->inq, false, 10); 

vá này từ năm trước khiến tôi tin rằng trở ERESTARTSYS từ một hàm gần/_release không phải là một tốt ý tưởng: http://us.generation-nt.com/answer/patch-fix-wrong-error-code-interrupted-close-syscalls-help-181191441.html

2

Không cần thử nghiệm này; vấn đề không phải là chấm dứt chương trình bất thường (mà, từ quan điểm của người lái xe của bạn, là chính xác như một bình thường close trên thiết bị) nhưng thay vì một vấn đề trong việc giữ trạng thái của thiết bị của bạn. Nói cách khác, nếu bạn đã chèn close(dev_fd) hoặc thậm chí exit(0) vào thời điểm chính xác nơi chương trình của bạn bị lỗi, bạn sẽ gặp phải vấn đề tương tự.

Bạn nên tìm hiểu xem phần nào trong hành vi của trình điều khiển đang khiến nó vẫn ở trạng thái bận và sửa lỗi đó.

+0

Tôi đã lấy lời khuyên của người làm hoang dã, ở trên và chèn một số cuộc gọi printk vào 'mything_release'. Tôi tìm thấy một dòng mà đọc 'if (wait_event_interruptible_timeout (port-> inq, false, 10)) return -ERESTARTSYS;', và nhận ra rằng với chấm dứt bất thường, nó không bao giờ vượt qua dòng đó. Google làm cho tôi nghĩ rằng ERESTARTSYS không phải là một điều ok để trở về từ một chức năng gần gũi. – Dave

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