2015-04-01 18 views
6

Tôi đang viết trình điều khiển hạt nhân Linux và cho mọi chức năng gửi dữ liệu đến không gian người dùng hoặc đọc dữ liệu từ không gian người dùng, tôi đang sử dụng copy_to_user() và copy_from_user(). Câu hỏi của tôi là: tôi có cần phải sử dụng các cuộc gọi này nếu tôi chỉ sao chép một kiểu dữ liệu cơ bản như một u32 hoặc int?copy_to_user() và copy_from_user() cho kiểu dữ liệu cơ bản

+0

Có một số nhầm lẫn về những gì bạn đang yêu cầu. Một khai báo hàm mẫu, cho biết bạn đang truyền một 'int' hay một con trỏ tới' int', sẽ hữu ích. Hai câu trả lời được đăng cho đến nay dựa trên hai cách giải thích khác nhau của câu hỏi của bạn. –

Trả lời

7

Nếu hàm nhận được con trỏ cho dữ liệu không gian người dùng, bạn phải sử dụng copy_from_user() để sao chép dữ liệu được trỏ từ không gian người dùng vào không gian hạt nhân (và ngược lại). Lưu ý rằng giá trị con trỏ chính nó được truyền theo giá trị (như tất cả các tham số C), vì vậy bạn không phải thực hiện copy_from_user() để lấy giá trị con trỏ trước khi bạn có thể thu thập dữ liệu trỏ đến copy_from_user().

Đối số bằng số làm việc giống như đối số con trỏ; trong C, cả hai đều là vô hướng. Bạn không phải sử dụng copy_from_user() để sao chép giá trị của thông số; đã được sao chép. Bạn chỉ phải sử dụng nó để sao chép dữ liệu được trỏ đến bởi một con trỏ được truyền.

Vì vậy, nếu bạn có thông số loại int, bạn có thể sử dụng trực tiếp. Nếu tham số của bạn trỏ đến một số int thì đối tượng int sẽ ở trong không gian người dùng và bạn cần sử dụng copy_to_user để sao chép giá trị của đối tượng đó vào không gian hạt nhân.

+0

Tôi không đồng ý với bạn. giả sử một con trỏ trong không gian người dùng không phải là trang liên kết và bạn phải lắp ráp cả hai phần của con trỏ để hoàn thành nó? Điều duy nhất bạn nhận được từ người dùng đã là tham số cho cuộc gọi là con trỏ người dùng, nhưng nếu nó trỏ đến một con trỏ người dùng khác, con trỏ đó phải được mua lại với user_copy. Trong môi trường 64 bit, một con trỏ người dùng rộng 8 byte và có thể được chia thành một ranh giới trang, vì vậy bạn sẽ cần phải gắn các bảng trang ảo để dịch nó từ không gian người dùng sang hạt nhân. Ngoài ra, các trang không gian người dùng có thể được hoán đổi, vì vậy hãy cẩn thận với điều này. –

+0

Khi bạn nói con trỏ không được căn chỉnh, bạn có ý nói rằng đối tượng con trỏ chính nó không được căn chỉnh, hoặc dữ liệu mà nó trỏ đến? Con trỏ là vô hướng và luôn được truyền theo giá trị. Nếu một cuộc gọi hệ thống có, nói, một tham số 'void *', hàm hạt nhân xử lý cuộc gọi hệ thống sẽ nhận được một * bản sao * của con trỏ; sự liên kết của đối tượng con trỏ trên phía người gọi là không liên quan. –

+0

Đối với con trỏ của các kiểu dữ liệu đơn giản (như 'int *'), 'put_user' và' get_user' cũng có thể được sử dụng. – holgac

2

Khi người dùng chuyển dữ liệu vào không gian hạt nhân, dữ liệu này có thể được chia nhỏ trên nhiều trang và các trang này có thể ngay cả trong hoán đổi bộ nhớ. Trong những trường hợp này, bạn sẽ phải đợi hạt nhân hoán đổi trong trang và truy cập vào trang có dữ liệu. Trong trường hợp các kiểu dữ liệu sơ cấp (như int hoặc con trỏ) thì cũng đúng là một số kiến ​​trúc (đáng chú ý là x86 intel) không ép buộc người dùng căn chỉnh dữ liệu sao cho ngay cả một số nguyên cũng có thể được phân chia xung quanh một đường viền trang. Bạn có thể có quyền truy cập vào phần đầu tiên của số nguyên, nhưng phải chờ phần thứ hai được quản lý bộ nhớ hoán đổi trước khi toàn bộ điều được truy cập.

Bạn có thể lưu một số vòng tròn bằng cách đặt tất cả dữ liệu người dùng vào một cấu trúc có con trỏ được chuyển đến hạt nhân. Bạn có thể copy_from_user nó như là một khối và lưu truy cập (và chạy vào nguy cơ bị chặn nhiều lần)

Vì vậy, và như là một kết luận, sử dụng các chức năng ngay cả đối với các loại cơ bản, như có rất nhiều trong số họ. Đừng giả sử bất cứ điều gì về nơi dữ liệu người dùng có thể được khi chạy trong chế độ hạt nhân. Bạn có quyền truy cập vào nó, nhưng địa chỉ ảo hạt nhân của dữ liệu người dùng không có gì để làm với các địa chỉ ảo nhìn thấy trong chế độ người dùng.

+0

Luis: Tôi nghĩ bạn đã hiểu sai OP. Tất cả các OP đang cố gắng làm là vượt qua một giá trị duy nhất của một kiểu dữ liệu cơ bản. OP thực sự hỏi liệu có thể truyền dữ liệu cơ bản theo giá trị thay vì tham chiếu hay không. Như @Keith đã chỉ ra, thông thường một con trỏ được truyền vào, và con trỏ IS này được truyền theo giá trị để nó có thể được truy cập trực tiếp. Tuy nhiên nếu bạn muốn dereference con trỏ người dùng, bạn phải sử dụng hàm copy_from_user() hoặc get_user() khi trong kernel. –

+0

Xin lỗi, nhưng như anh ta nói: * Nếu tôi chỉ sao chép một kiểu dữ liệu cơ bản như một bản sao có nghĩa là sao chép, vì vậy tôi cho rằng int được truyền bằng tham chiếu (để trả về một số giá trị, ví dụ) nếu anh ta chỉ chuyển một giá trị cho nhân (nhưng không quay lại không gian người dùng) thì anh ta có thể làm như thế này. Tôi không nghĩ về ioctl đó là nơi điều này có ý nghĩa. Giả sử anh ta đang cố gắng 'int a; viết (fc, & a, sizeof a); '... –

+0

Tất nhiên bạn có thể ** sử dụng ** con trỏ được chuyển tới không gian hạt nhân trong ** viết (2) ** dưới dạng dữ liệu, nhưng không có ý nghĩa nhiều khi tạo lái xe như thế này Anh ấy nói * ... và với mọi chức năng ... * –

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