<div dir="ltr">And this is exactly my debate.<div><br></div><div>On the one hand, using protobuf (or flatbuffers, or cap'nproto, or JSON, or msgpack, or whatever standard serialization format) has its share of complexity. You have to find the end of the struct, you have to have a parser both in kernel and in userspace, etc.</div><div><br></div><div>On the other hand, what we're seeing here is, to paraphrase Greenspun, an ad hoc, informally-specified, bug-ridden, slow implementation of half of protocol buffers ;-)</div><div><br></div><div>Given we're adding protobuf parser to the module, we can access it relatively easily from any programming language, we do need need a special syscall or include special headers (you need to get the ioctl number from the running module version). And we're getting more features (i.e., ZigZag encoding of integers, backwards compatibility) for free.</div><div><br></div><div>I can definitely see your point that sticking to C structs is simpler for many things, but standard serialization could be simpler for others.</div><div><br></div><div>PS</div><div>Since you mentioned copy_from_user, I think it's worth mentioning that the reason for not accessing user's memory directly, is that without copy_from_user, the data could be swapped out in the middle of the memcpy. Or at least this is one of the reasons.</div><div><br></div><div>Thanks,</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 30, 2015 at 5:08 PM, Gilboa Davara <span dir="ltr"><<a href="mailto:gilboad@gmail.com" target="_blank">gilboad@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Mon, Mar 30, 2015 at 3:44 PM, Elazar Leibovich <<a href="mailto:elazarl@gmail.com">elazarl@gmail.com</a>> wrote:<br>
> Sounds good, thanks (although it'll be harder to use from non-C programs).<br>
<br>
</span>I usually complement each kernel module with a user-mode C library<br>
wrapped inside a nice / easy to use (...) C++ class that handles the<br>
"difficult bits".<br>
It far easier to make a C++ class that handles idiot-proof (E.g.<br>
string commands) data than doing it inside the kernel.<br>
(Plus, when a user mode library goes up the flame due to bad input,<br>
you don't end up with a dead machine...)<br>
<span class=""><br>
> Do you have a good idea how to stream information as a response to ioctl?<br>
<br>
</span>Use TLV (type / length / value-array).<br>
<br>
typedef union _answer_data_ {<br>
<span class="">       int __out error_code;<br>
       int   __out next_answer_time;<br>
       struct access_info {<br>
              int __out access_count;<br>
              int __out user_count;<br>
       };<br>
</span>} answer_data_t;<br>
<span class=""><br>
typedef struct _debug_request_<br>
{<br>
     request_t request_type;<br>
     void *request_pointer;<br>
</span>     answer_t answer_type;  <--------------- Answer type. ( Enum, define, etc ).<br>
     int answer_buffer_size;  <--------------- User supplied answer<br>
buffer size (in answer_data union units).<br>
     int __out answer_buffer_used;  <-------- Answer buffer used size<br>
(number of answers copied by the kernel).<br>
     answer_data_t *answer_data_array; <-- Answer buffer array<br>
(user-mode pointer).<br>
} debug_request_t;<br>
<br>
Now, in-case of multiple answers, you simply<br>
copy_to_user((void *)&debug_request_copy->answer_data_array[count],<br>
                    (void *)&kernel_answer,<br>
                    sizeof(answer_data_t));<br>
count ++;<br>
<br>
.. To copy each answer to the user buffer.<br>
Once the array is depleted, the kernel function returns with a valid<br>
error code (E.g. -EEXIST) and tells to the user mode caller that<br>
there's additional data to be read (E.g. until the kernel returns<br>
-EWOULDBLOCK).<br>
<br>
Alternatively (and somewhat more complex) you can setup mmap over file<br>
handle, and simply map a static kernel buffer directly to the user<br>
mode. Though, unless you need to stream huge amounts of data and/or<br>
ioctl performance penalty [50-200ns] is too high, I wouldn't bother.<br>
<br>
BTW, Most likely your are aware of this, but just in case, never<br>
access the user mode buffer directly. When you first access the<br>
request buffer you copy it (copy_from_user) to kernel debug_request<br>
(no need to allocate it, considering its size, you shouldn't have any<br>
issues using stack, even on i386).<br>
<span class="HOEnZb"><font color="#888888"><br>
- Gilboa<br>
</font></span></blockquote></div><br></div>