2012-11-23 21 views
9

Tôi đang viết một phần mở rộng hạt nhân OSX cho trình điều khiển thiết bị âm thanh (phần mềm của nó, nhưng mô phỏng thiết bị phần cứng).Không thể bỏ mở rộng hạt nhân; Các lớp có trường hợp

Trong quá trình phát triển, sẽ thuận tiện để gỡ cài đặt hoàn toàn các phiên bản cũ hiện có và sau đó xây dựng và cài đặt phiên bản mới từ đầu. Tuy nhiên, điều này đôi khi dường như không thể thực hiện được nếu không có hệ thống khởi động lại.

Bản thân chương trình không chạy và các tệp nguồn đã bị xóa khỏi thư mục /System/Library/Extensions/.

Nhưng kextstat cho thấy một trường hợp duy nhất:

$ kextstat | grep 'com.foo.driver.bar' 
219 0 0xfff123 0x5000 0x5000 com.foo.driver.bar (0.0.1) <102 5 4 3> 

(... nghĩa :)

Index Refs Address Size Wired Name (Version) <Linked Against> 

Vì vậy, có 0 Refs để dụ người lái xe của tôi, nhưng kextunload đôi khi sẽ thất bại, phàn nàn về các phiên bản hiện tại:

$ sudo kextunload -b com.foo.driver.bar 
(kernel) Can't unload kext com.foo.driver.bar; classes have instances: 
(kernel)  Kext com.foo.driver.bar class FooBarDriver has 1 instance. 
(kernel)  Kext com.foo.driver.bar class com_foo_driver_bar has 1 instance. 
Failed to unload com.foo.driver.bar - (libkern/kext) kext is in use or retained (cannot unload). 

Khi điều này xảy ra, thứ Không có cách nào để "buộc" dỡ bỏ kext (mà tôi biết).

Tôi có đoán đúng rằng trường hợp đơn lẻ này vẫn tồn tại do tham chiếu được giữ trong bộ nhớ bởi hạt nhân OS đang chạy không? Điều đó có vẻ không đúng, bởi vì sau đó kextunload sẽ luôn thất bại. Vậy tại sao chỉ kextunload đôi khi yêu cầu khởi động lại hệ thống để "hoàn toàn" dỡ tất cả các phiên bản trình điều khiển?

Trả lời

10

Chạy kextunload cho IOKit kext sẽ (nếu không có kexts phụ thuộc vào nó) khiến hạt nhân cố gắng terminate() bất kỳ phiên bản nào của lớp trong kext đó trong sổ kiểm nhập I/O Kit. Sau đó nó sẽ đợi một chút và kiểm tra xem có bất kỳ lớp nào của kext vẫn có các cá thể không. Nếu không, nó sẽ giải phóng kext. Nếu các trường hợp còn lại, kextunload không thành công (các trường hợp đã kết thúc vẫn bị chấm dứt, mặc dù vậy, điều này có nghĩa là bộ khớp I/O không được chạy lại trên các nhà cung cấp của chúng).

Vì vậy, bằng cách nào đó, bạn vẫn kết thúc với các phiên bản trực tiếp.

  • Một khả năng là đối tượng của bạn từ chối terminate(). Điều này có thể xảy ra nếu họ có khách hàng không từ bỏ quyền kiểm soát, ví dụ: bạn không thể gỡ bỏ trình điều khiển cho một đĩa với hệ thống tập tin được gắn trên đầu trang. Không gian người dùng không đáp ứng với các thông báo chấm dứt là một ví dụ khác.

  • Nếu không, các phiên bản kết thúc, nhưng không được giải phóng. Vì chúng dường như là hai trong số các lớp trình điều khiển chính của bạn, nếu bạn không có bất kỳ ứng dụng khách nào sẽ không từ bỏ yêu cầu của họ, tôi sẽ đi ra ngoài và gợi ý rằng bạn có thể có tham chiếu vòng tròn . Nếu không phải vậy, bạn sẽ phải tìm kiếm retain() s không khớp với số release(). Tôi đưa ra một số mẹo về cách theo dõi các số này xuống in this answer.

Nếu các trường hợp chấm dứt và được deregistered, họ sẽ không còn xuất hiện trong kết quả của công cụ ioreg commandline, vì vậy đó là một cách dễ dàng kiểm tra nào trong hai trường hợp áp dụng ở đây.

+0

Hữu ích. Cảm ơn! – pje

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