<div dir="ltr"><div>hi all:</div><div><span class="" style="white-space:pre">        </span>I have a kernel module, it provide some functions:</div><div>1. vmalloc a 4KB memory space (I built a ring buffer manage the 4KB memory space)</div>
<div>2. provide the special mmap(), which can remap the memory space.</div><div>3. write some data into the 4KB memory space </div><div><br></div><div>And I have a userspace program, it provide some functions:</div><div>1.mmap the kernel memory space into userspace </div>
<div>2.read some data from that mmap space</div><div><br></div><div>The question is:</div><div>When I first insmod the kernel module until the data have written in the space, </div><div>I run the userspace program which read some data. This way is OK.</div>
<div>If I insmod the kernel module and run the userspace program at the same time, </div><div>the kernel will stop and computer will reboot. I think the kernel module is </div><div>writing the data and the userspace program is reading the data.  </div>
<div><br></div><div>How to fix it, thank you!</div><div><br></div><div>the kernel module code is:</div><div>#####################################################</div><div>#include &lt;linux/module.h&gt;</div><div>#include &lt;linux/kernel.h&gt;</div>
<div>#include &lt;linux/fs.h&gt;</div><div>#include &lt;linux/errno.h&gt;</div><div>#include &lt;linux/types.h&gt;</div><div>#include &lt;linux/fcntl.h&gt;</div><div>#include &lt;linux/cdev.h&gt;</div><div>#include &lt;linux/version.h&gt;</div>
<div>#include &lt;linux/vmalloc.h&gt;</div><div>#include &lt;linux/ctype.h&gt;</div><div>#include &lt;linux/pagemap.h&gt;</div><div>#include &lt;linux/mm.h&gt;</div><div>#include &lt;linux/slab.h&gt;</div><div>#include &lt;linux/proc_fs.h&gt;</div>
<div>#include &lt;asm/io.h&gt;</div><div>#include &lt;asm/system.h&gt;</div><div>#include &lt;linux/uaccess.h&gt;</div><div>#include &lt;linux/timer.h&gt;</div><div>#include &lt;linux/pid.h&gt;</div><div>#include &lt;linux/sched.h&gt;</div>
<div>//#define USE_KMALLOC </div><div><br></div><div>#define PAGE_ORDER   0</div><div>#define PAGES_NUMBER 1</div><div><br></div><div>static int MAJOR_DEVICE = 30;</div><div>void * mmap_buf = 0;</div><div>unsigned long mmap_size = 4*1024;</div>
<div><br></div><div>static int ws_open(struct inode *inode, struct file *file)</div><div>{</div><div>    return 0;    </div><div>}</div><div><br></div><div><br></div><div>#if LINUX_VERSION_CODE &lt; KERNEL_VERSION(2,6,36)<span class="" style="white-space:pre">        </span></div>
<div>#define LIN_IOCTL_NAME<span class="" style="white-space:pre">        </span>.ioctl</div><div>int ws_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long data)</div><div>#else</div><div>#define LIN_IOCTL_NAME<span class="" style="white-space:pre">        </span>.unlocked_ioctl</div>
<div>long ws_ioctl(struct file *file, u_int cmd, u_long data)</div><div>#endif</div><div>{</div><div>    //todo</div><div>    return 0;    </div><div>}</div><div><br></div><div><br></div><div>int mmap_alloc(void)</div><div>
{</div><div>    //struct page *page;</div><div>    int i;    </div><div>    mmap_size = PAGE_ALIGN(mmap_size);</div><div><br></div><div>    #ifdef USE_KMALLOC //for kmalloc</div><div>    mmap_buf = kzalloc(mmap_size, GFP_KERNEL);</div>
<div>    printk(&quot;kmalloc mmap_buf=%p\n&quot;, (void *)mmap_buf);</div><div>    if (!mmap_buf) {</div><div><span class="" style="white-space:pre">        </span>printk(&quot;kmalloc failed!\n&quot;);</div><div>        return -1;</div>
<div>    }</div><div>    for (page = virt_to_page(mmap_buf); page &lt; virt_to_page(mmap_buf + mmap_size); page++) {</div><div>        SetPageReserved(page);</div><div><span class="" style="white-space:pre">        </span>strcpy((void *)mmap_buf, &quot;Hello world!\n&quot;);</div>
<div>    }</div><div>    #else //for vmalloc</div><div>    mmap_buf  = vmalloc(mmap_size);</div><div>    printk(&quot;vmalloc mmap_buf=%p  mmap_size=%ld\n&quot;, (void *)mmap_buf, mmap_size);</div><div>    if (!mmap_buf ) {</div>
<div><span class="" style="white-space:pre">        </span>printk(&quot;vmalloc failed!\n&quot;);</div><div>        return -1;</div><div>    }</div><div>    for (i = 0; i &lt; mmap_size; i += PAGE_SIZE) {</div><div>        SetPageReserved(vmalloc_to_page(mmap_buf + i));</div>
<div>    }</div><div>    #endif</div><div><br></div><div>  return 0;</div><div>}</div><div><br></div><div><br></div><div>int mmap_free(void)</div><div>{</div><div>    #ifdef USE_KMALLOC</div><div>    struct page *page;</div>
<div>    for (page = virt_to_page(mmap_buf); page &lt; virt_to_page(mmap_buf + mmap_size); page++) {</div><div>        ClearPageReserved(page);</div><div>    }</div><div>    kfree((void *)mmap_buf);</div><div>    #else</div>
<div>    int i;</div><div>    for (i = 0; i &lt; mmap_size; i += PAGE_SIZE) {</div><div>        ClearPageReserved(vmalloc_to_page(mmap_buf + i));</div><div>    }</div><div>    vfree((void *)mmap_buf);</div><div>    #endif</div>
<div>    mmap_buf = NULL;</div><div>    return 0;</div><div>}</div><div><br></div><div><br></div><div>static int ws_mmap(struct file *f, struct vm_area_struct *vma)</div><div>{</div><div>    int ret;</div><div>    unsigned long pfn;</div>
<div>    unsigned long start = vma-&gt;vm_start;</div><div>    unsigned long size = PAGE_ALIGN(vma-&gt;vm_end - vma-&gt;vm_start);</div><div>    void * ptmp = mmap_buf;</div><div>    if (size &gt; mmap_size || !mmap_buf) {</div>
<div>        return -EINVAL;</div><div>    }</div><div>    </div><div>    #ifdef USE_KMALLOC</div><div><span class="" style="white-space:pre">        </span>pfn  = virt_to_phys(mmap_buf) &gt;&gt; PAGE_SHIFT;</div><div>        return remap_pfn_range(vma, start,  pfn, size, PAGE_SHARED);</div>
<div>    #else</div><div>    /* loop over all pages, map it page individually */</div><div>    while (size &gt; 0) {</div><div>        pfn = vmalloc_to_pfn(ptmp);</div><div>        if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) &lt; 0) {</div>
<div>            return ret;</div><div>        }</div><div>        start += PAGE_SIZE;</div><div>        ptmp += PAGE_SIZE;</div><div>        size -= PAGE_SIZE;</div><div>    }</div><div>    #endif</div><div>    return 0;</div>
<div>    </div><div>}</div><div><br></div><div><br></div><div>static int ws_release(struct inode *inode, struct file *file)</div><div>{</div><div>    return 0;</div><div>}</div><div><br></div><div><br></div><div>static const struct file_operations ws_fops ={    </div>
<div>    .owner = THIS_MODULE,</div><div>     //.write = ws_write,</div><div>    //.read = ws_read,</div><div>    .mmap = ws_mmap,</div><div>    //.ioctl = ws_ioctl,</div><div>    //.open = ws_open,</div><div>    //.release = ws_release,</div>
<div>};</div><div><br></div><div>static void wsmmap_exit(void)</div><div>{</div><div>    if( 0 != mmap_free( ))</div><div>        printk(&quot;mmap free failed!\n&quot;);</div><div>    unregister_chrdev(MAJOR_DEVICE,&quot;wsmmap&quot;); </div>
<div>    printk(&quot;rmmod wsmmap module!\n&quot;);</div><div>      </div><div>}</div><div><br></div><div><br></div><div>/*manage data*/</div><div>typedef struct {</div><div>         char *buffer;</div><div>         int length;</div>
<div>         volatile int start;</div><div>         volatile int end;</div><div>} RingBuffer;</div><div><br></div><div>RingBuffer * ring_buffer;</div><div><br></div><div>RingBuffer *RingBuffer_create(void *start_malloc, int length)</div>
<div>{</div><div>         RingBuffer *buffer = (RingBuffer *)start_malloc;</div><div>         buffer-&gt;length  = length + 1;</div><div>         buffer-&gt;start = 0;</div><div>         buffer-&gt;end = 0;</div><div>         buffer-&gt;buffer = (char *)start_malloc + sizeof(RingBuffer);</div>
<div><br></div><div><span class="" style="white-space:pre">        </span>return buffer;</div><div>}</div><div><br></div><div>#define RingBuffer_available_data(B) ((B)-&gt;end % (B)-&gt;length - (B)-&gt;start)</div><div>#define RingBuffer_available_space(B) ((B)-&gt;length - (B)-&gt;end - 1)</div>
<div>#define RingBuffer_commit_write(B, A) ((B)-&gt;end = ((B)-&gt;end + (A)) % (B)-&gt;length)</div><div>#define RingBuffer_ends_at(B) ((B)-&gt;buffer + (B)-&gt;end)</div><div><br></div><div>int RingBuffer_write(RingBuffer *buffer, char *data, int length)</div>
<div>{</div><div><span class="" style="white-space:pre">        </span></div><div><span class="" style="white-space:pre">        </span>if(RingBuffer_available_data(buffer) == 0) {</div><div><span class="" style="white-space:pre">                </span>buffer-&gt;start = buffer-&gt;end = 0;</div>
<div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre">        </span></div><div><span class="" style="white-space:pre">        </span>if (length &gt; RingBuffer_available_space(buffer)){</div>
<div><span class="" style="white-space:pre">                </span>printk(&quot;Not enough space: %d request, %d available&quot;, RingBuffer_available_data(buffer), length);</div><div><span class="" style="white-space:pre">                </span>return -1;</div>
<div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre">        </span>void *result = memcpy(RingBuffer_ends_at(buffer), data, length);</div><div><span class="" style="white-space:pre">        </span></div>
<div><span class="" style="white-space:pre">        </span>if (result != RingBuffer_ends_at(buffer)){</div><div><span class="" style="white-space:pre">                </span>printk(&quot;Failed to write data into buffer.&quot;);</div><div><span class="" style="white-space:pre">                </span>return -1;</div>
<div><span class="" style="white-space:pre">        </span>}</div><div><span class="" style="white-space:pre">        </span></div><div><span class="" style="white-space:pre">        </span>RingBuffer_commit_write(buffer, length);</div><div><br>
</div><div><span class="" style="white-space:pre">        </span>return length;</div><div>}</div><div><br></div><div><br></div><div>int kernel_thread_write(void *argc)</div><div>{</div><div><span class="" style="white-space:pre">        </span> char *a = &quot;aa&quot;;</div>
<div><span class="" style="white-space:pre">        </span> int num = 2038;</div><div><span class="" style="white-space:pre">        </span> while (num){</div><div><span class="" style="white-space:pre">                </span> RingBuffer_write(ring_buffer, a, 2);</div>
<div><span class="" style="white-space:pre">                </span> printk(&quot;write length is %d, start is %d, end is %d\n&quot;, ring_buffer-&gt;length, ring_buffer-&gt;start, ring_buffer-&gt;end);</div><div><span class="" style="white-space:pre">                </span> --num;</div>
<div><span class="" style="white-space:pre">                </span> msleep(10);</div><div><span class="" style="white-space:pre">        </span> }</div><div><span class="" style="white-space:pre">        </span>return 0;</div><div>}</div><div><br></div>
<div>int wsmmap_init(void)</div><div>{</div><div>    //int i;</div><div>    if(register_chrdev(MAJOR_DEVICE, &quot;wsmmap&quot;, &amp;ws_fops))</div><div>   <span class="" style="white-space:pre">        </span>    printk(&quot;Cannot register mmap device as major device 0!\n&quot;);</div>
<div>   <span class="" style="white-space:pre">        </span>else </div><div>            printk(&quot;wsmmap device driver registed sucessfully!\n&quot;); </div><div>    printk(&quot;insmod wsmmap module successfully!\n&quot;);    </div>
<div>    if(0 != mmap_alloc( ))</div><div>        printk(&quot;mmap alloc failed!\n&quot;);</div><div><br></div><div>   /*</div><div>    * Initialization RingBuffer</div><div>    */</div><div>    ring_buffer = RingBuffer_create(mmap_buf, mmap_size - sizeof(RingBuffer) - 1);</div>
<div><br></div><div>    kernel_thread(kernel_thread_write, NULL, CLONE_KERNEL);</div><div>   </div><div>    /*</div><div>    int i; </div><div>    for (i = 0; i &lt; mmap_size; i += PAGE_SIZE){</div><div><span class="" style="white-space:pre">        </span>memset(mmap_buf + i, &#39;a&#39;, PAGE_SIZE);</div>
<div><span class="" style="white-space:pre">        </span>memset(mmap_buf + i + PAGE_SIZE - 1, &#39;\0&#39;, 1);</div><div>    }*/</div><div>    return 0;</div><div>}</div><div><br></div><div><br></div><div>module_init(wsmmap_init);</div>
<div>module_exit(wsmmap_exit);</div><div><br></div><div>MODULE_LICENSE(&quot;GPL&quot;);</div><div>MODULE_VERSION(&quot;1.0.0&quot;);</div><div>MODULE_DESCRIPTION(&quot;wskmmap&quot;);</div><div>MODULE_AUTHOR(&quot;wssys&quot;);</div>
<div><br></div><div>#####################################################</div><div><br></div><div>the userspace code is:</div><div>#####################################################</div><div>#include &lt;stdio.h&gt;</div>
<div>#include &lt;stdlib.h&gt;</div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;sys/mman.h&gt;</div><div>#include &lt;sys/types.h&gt;</div><div>#include &lt;sys/stat.h&gt;</div><div>#include &lt;fcntl.h&gt;</div>
<div>#include &lt;string.h&gt;</div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;pthread.h&gt;</div><div><br></div><div><br></div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;stdio.h&gt;</div><div>#include &lt;execinfo.h&gt;</div>
<div>#include &lt;signal.h&gt;</div><div>#include &lt;stdlib.h&gt;</div><div>#include &lt;sys/types.h&gt;</div><div>#include &lt;sys/stat.h&gt;</div><div>#include &lt;fcntl.h&gt;</div><div>#include &lt;time.h&gt;</div><div>
#include &lt;string.h&gt;</div><div><br></div><div>void handler(int sig)</div><div>{</div><div>#ifndef WIN32</div><div><span class="" style="white-space:pre">        </span>void *array[10];</div><div><span class="" style="white-space:pre">        </span>size_t size;</div>
<div><span class="" style="white-space:pre">        </span>size = backtrace(array, 10);</div><div><span class="" style="white-space:pre">        </span>int file_dump = open(&quot;/opt/dump.log&quot;, O_APPEND | O_RDWR);</div><div><span class="" style="white-space:pre">        </span>char message[7] = &quot;BEGIN &quot;;</div>
<div><span class="" style="white-space:pre">        </span>write(file_dump, message, 7);</div><div><br></div><div><span class="" style="white-space:pre">        </span>time_t now;</div><div><span class="" style="white-space:pre">        </span>struct tm *timenow;</div>
<div><span class="" style="white-space:pre">        </span>char strtemp[255];</div><div><br></div><div><span class="" style="white-space:pre">        </span>time(&amp;now);  </div><div><span class="" style="white-space:pre">        </span>timenow = localtime(&amp;now);</div>
<div><span class="" style="white-space:pre">        </span>sprintf(strtemp, &quot;recent time is : %s\n&quot;, asctime(timenow));</div><div><br></div><div><span class="" style="white-space:pre">        </span>int length=strlen(strtemp)+1;</div>
<div><span class="" style="white-space:pre">        </span>write(file_dump, strtemp, length);</div><div><br></div><div><span class="" style="white-space:pre">        </span>backtrace_symbols_fd(array, size, file_dump);</div><div><br></div>
<div><span class="" style="white-space:pre">        </span>close(file_dump);</div><div><br></div><div><span class="" style="white-space:pre">        </span>exit(1);</div><div>#endif</div><div>}</div><div><br></div><div><br></div><div>unsigned long phymem_addr = 0;</div>
<div>unsigned long phymem_size = 4*1024;</div><div><br></div><div>/*manage data*/</div><div>typedef struct {</div><div>   char *buffer;</div><div>   int length;</div><div>   volatile int start;</div><div>   volatile int end;</div>
<div>} RingBuffer;</div><div><br></div><div>RingBuffer *ring;</div><div>int read_dump;</div><div><br></div><div>#define RingBuffer_available_data(B) ((B)-&gt;end % (B)-&gt;length - (B)-&gt;start)</div><div>#define RingBuffer_starts_at(B) ((B)-&gt;buffer + (B)-&gt;start)</div>
<div>#define RingBuffer_commit_read(B, A) ((B)-&gt;start = ((B)-&gt;start + (A)) % (B)-&gt;length)</div><div>#define RingBuffer_available_space(B) ((B)-&gt;length - (B)-&gt;end - 1)</div><div>#define RingBuffer_commit_write(B, A) ((B)-&gt;end = ((B)-&gt;end + (A)) % (B)-&gt;length)</div>
<div>#define RingBuffer_ends_at(B) ((B)-&gt;buffer + (B)-&gt;end)</div><div><br></div><div><br></div><div><br></div><div>int RingBuffer_read(RingBuffer *buffer, char *target, int amount)</div><div>{</div><div>      </div>
<div>       if (amount &gt; RingBuffer_available_data(buffer)){</div><div>                printf(&quot;Not enough in the buffer: has %d, needs %d&quot;, RingBuffer_available_data(buffer), amount);</div><div>                return -1;</div>
<div>        }</div><div> </div><div>     </div><div>        void *result = memcpy(target, RingBuffer_starts_at(buffer), amount);</div><div>     </div><div>        if (result != target){</div><div>                 printf(&quot;Failed to write buffer into data.&quot;);</div>
<div>                 return -1;</div><div>        }</div><div><br></div><div>  </div><div>       RingBuffer_commit_read(buffer, amount);</div><div>     </div><div> </div><div>        if(buffer-&gt;end == buffer-&gt;start) {</div>
<div>                 buffer-&gt;start = buffer-&gt;end = 0;</div><div>        }</div><div>      </div><div>        </div><div><span class="" style="white-space:pre">        </span>return amount;</div><div>}</div><div><br></div>
<div><br></div><div>void *thread_read(void *arg)</div><div>{</div><div><span class="" style="white-space:pre">        </span>char mem_data[64];</div><div><span class="" style="white-space:pre">        </span>int num = 2038;</div><div><br>
</div><div><span class="" style="white-space:pre">        </span>while (num){</div><div><span class="" style="white-space:pre">                </span>RingBuffer_read(ring, mem_data, 2);</div><div><span class="" style="white-space:pre">                </span>mem_data[2] = &#39;\0&#39;;</div>
<div><span class="" style="white-space:pre">                </span>printf(&quot;read length is %d, start is %d, end is %d, data is %s\n&quot;, ring-&gt;length, ring-&gt;start, ring-&gt;end, mem_data);</div><div><span class="" style="white-space:pre">                </span>--num;</div>
<div><span class="" style="white-space:pre">                </span>sleep(1);</div><div><span class="" style="white-space:pre">        </span>}</div><div>}</div><div><br></div><div>int main(void)</div><div>{</div><div><span class="" style="white-space:pre">        </span>int fd;</div>
<div><span class="" style="white-space:pre">        </span>int i=0;</div><div><span class="" style="white-space:pre">        </span>void *mmap_addr = NULL;</div><div><br></div><div><span class="" style="white-space:pre">        </span>signal(SIGSEGV, handler);   // install our handler</div>
<div><br></div><div><span class="" style="white-space:pre">        </span>fd = open(&quot;/dev/wsmmap&quot;, O_RDWR);</div><div><span class="" style="white-space:pre">        </span>if(fd &lt; 0) {</div><div><span class="" style="white-space:pre">                </span>perror(&quot;open&quot;);</div>
<div><span class="" style="white-space:pre">                </span>return 0;</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre">        </span>mmap_addr = mmap(NULL, phymem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);</div>
<div><span class="" style="white-space:pre">        </span>if(mmap_addr == MAP_FAILED) {</div><div><span class="" style="white-space:pre">                </span>perror(&quot;mmap&quot;);</div><div><span class="" style="white-space:pre">        </span> <span class="" style="white-space:pre">        </span>return 0;</div>
<div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre">        </span>ring = (RingBuffer *)mmap_addr;</div><div><span class="" style="white-space:pre">        </span>ring-&gt;buffer = mmap_addr + sizeof(RingBuffer);<span class="" style="white-space:pre">        </span></div>
<div><br></div><div><span class="" style="white-space:pre">        </span></div><div><span class="" style="white-space:pre">        </span>int res;</div><div><span class="" style="white-space:pre">        </span>pthread_t t_read;</div><div><span class="" style="white-space:pre">        </span></div>
<div><span class="" style="white-space:pre">        </span>res = pthread_create(&amp;t_read, NULL, thread_read, NULL);</div><div><span class="" style="white-space:pre">        </span>if (res != 0){</div><div><span class="" style="white-space:pre">                </span>perror(&quot;join failed&quot;);</div>
<div><span class="" style="white-space:pre">                </span>return -1;</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre">        </span>void *thread_r_read;</div>
<div><span class="" style="white-space:pre">        </span>res = pthread_join(t_read, &amp;thread_r_read);</div><div><span class="" style="white-space:pre">        </span>if (res != 0){</div><div><span class="" style="white-space:pre">                </span>perror(&quot;Thread join failed&quot;);</div>
<div><span class="" style="white-space:pre">                </span>return -1;</div><div><span class="" style="white-space:pre">        </span>}</div><div><span class="" style="white-space:pre">        </span></div><div><span class="" style="white-space:pre">        </span>free(mmap_addr);</div>
<div><span class="" style="white-space:pre">        </span>mmap_addr=NULL;</div><div>       <span class="" style="white-space:pre">        </span>close(fd); </div><div>    <span class="" style="white-space:pre">        </span>return 0;    </div>
<div>}</div><div><br></div><div>#####################################################</div><div><br></div><div> </div></div>