나는 64에 리눅스 3.10.45에 대한 커널 모듈 (하드웨어에 대한 스트레스 테스트 도구) 구축을 위해 노력하고 발견되지 mutex_lock_nested. 뮤텍스를 추가 할 때까지 지금까지 제대로 작동하는 것처럼 보였습니다. 커널 모듈이 연결되지 않습니다 - 기호는
제가
사용 뮤텍스와 기능 mutex_init, mutex_lock, mutex_unlock 및 mutex_destroy 첨가. 'insmod 명령'로로드 할 때 모듈을 구축는 dmesg 명령에서 오류 메시지가 오류 또는 경고를 나왔고,하지만 : 나는 '알 수없는 기호'로, 가끔하는 데 도움이 힌트를 발견
[76603.744551] tryBlk: Unknown symbol mutex_lock_nested (err 0)
[76603.744574] tryBlk: Unknown symbol mutex_destroy (err 0)
MODULE_LICENSE ("GPL v2") 행을 추가하십시오.
차이가 없습니다.
linux/mutex.h를 보면 mutex_lock은 심볼 CONFIG_DEBUG_LOCK_ALLOC이 정의되어 있으면 mutex_lock_nested로 정의된다는 것을 알았습니다. 이것을 확인하면 내 .config 파일에 정의 된 것 같습니다. (건드릴 수는 없지만 기본적으로 kernel.org의 커널입니다.)
문제가 있습니까? 이 디버그 기능으로 모듈을 만들려면 모듈에 다른 것을 수동으로 추가해야합니까?
포함 파일 및 시퀀스를 변경하려고 시도했습니다. 차이 없음. 커널이 3.10.45로 변경하여
시스템, 데비안 7 '위지'의 x64를 실행 중입니다.
뮤텍스를 사용하는 파일 :
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include "ring.h"
struct RingBuf
{
unsigned char *buffer;
unsigned int size;
unsigned int inp,outp;
struct mutex mtx;
};
static int _bytesavail(struct RingBuf *self);
static int _spaceavail(struct RingBuf *self);
struct RingBuf *RingBuf_init(unsigned int size)
{
struct RingBuf *self;
if(size<16)size=16;
if(size>0x10000000u)return 0;
if(size & (size-1))
{
unsigned int ns;
// is not a power of 2.
size = size<<1;
while(1)
{
ns=size&(size-1);
if(!ns)break;
size=ns;
}
}
self = (struct RingBuf*)vmalloc(sizeof(*self)+size);
memset(self , 0 , sizeof(*self));
self->buffer = (unsigned char*)(self+1);
self->size = size;
self->inp = 0;
self->outp = 0;
mutex_init(&(self->mtx));
return self;
}
void RingBuf_uninit(struct RingBuf *self)
{
if(!self)return;
mutex_lock(&(self->mtx));
mutex_destroy(&(self->mtx));
memset(self , 0xFE , sizeof(*self));
vfree(self);
}
int RingBuf_add(struct RingBuf *self,const void *data,int num)
{
int cpy;
if(num<=0)return 0;
mutex_lock(&(self->mtx));
// check amount to copy
cpy = _spaceavail(self);
if(cpy>num)cpy=num;
// one part or split
if(self->inp+cpy <= self->size)
{
// one chunk
memcpy(self->buffer+self->inp , data , cpy);
}else{
int p1 = (self->size-self->inp);
// wrapped
memcpy(self->buffer+self->inp , data , p1);
memcpy(self->buffer , ((const unsigned char*)data)+p1 , cpy-p1);
}
self->inp = (self->inp+cpy) & (self->size-1) ;
mutex_unlock(&(self->mtx));
return cpy;
}
int RingBuf_get(struct RingBuf *self,void *data,int num)
{
int cpy;
if(num<=0)return 0;
mutex_lock(&(self->mtx));
// check amount to copy
cpy = _bytesavail(self);
if(cpy>num)cpy=num;
// one part or split
if(self->outp+cpy <= self->size)
{
// one chunk
memcpy(data , self->buffer+self->outp , cpy);
}else{
int p1 = (self->size-self->outp);
// wrapped
memcpy(data , self->buffer+self->outp , p1);
memcpy(((unsigned char*)data)+p1 , self->buffer , cpy-p1);
}
self->outp = (self->outp+cpy) & (self->size-1) ;
mutex_unlock(&(self->mtx));
return cpy;
}
int RingBuf_get_user(struct RingBuf *self,void __user *data,int num)
{
int cpy;
int ret;
if(num<=0)return 0;
mutex_lock(&(self->mtx));
// check amount to copy
cpy = _bytesavail(self);
if(cpy>num)cpy=num;
// one part or split
if(self->outp+cpy <= self->size)
{
// one chunk
ret = copy_to_user(data , self->buffer+self->outp , cpy);
}else{
int p1 = (self->size-self->outp);
// wrapped
ret = copy_to_user(data , self->buffer+self->outp , p1);
if(!ret)
ret = copy_to_user(((unsigned char*)data)+p1 , self->buffer , cpy-p1);
}
if(ret)return -1;
self->outp = (self->outp+cpy) & (self->size-1) ;
mutex_unlock(&(self->mtx));
return cpy;
}
int RingBuf_numBytes(struct RingBuf *self)
{
int result;
mutex_lock(&(self->mtx));
result = _bytesavail(self);
mutex_unlock(&(self->mtx));
return result;
}
static int _bytesavail(struct RingBuf *self)
{
return (self->inp-self->outp)&(self->size-1);
}
static int _spaceavail(struct RingBuf *self)
{
return (self->outp-self->inp-1)&(self->size-1);
}