copy_to_user不工作 - 我错在哪里?

时间:2012-05-29 04:47:32

标签: c copy kernel-module

当条件失败时,我试图从内核空间向用户空间发送一些消息!

这是我的内核代码:

#define MESSAGTOUSER 1

int ret_val;
struct siginfo sinfo;
pid_t id;
struct task_struct *task;

unsigned char msgBuffer[20];
unsigned char buf1[20]= "HI";

static int major_no;
static struct class *safe_class;

static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static int device_open(struct inode *inode, struct file *file);
static int device_write(struct file *file, const char *gdata, size_t len, loff_t *off);
static int device_read(struct file *file, char *buf, size_t len, loff_t *off);
static int device_release(struct inode *inode, struct file *file);


int failureDetection (char* faultMsg) {
    strcpy (msgBuffer, faultMsg);
    printk(KERN_ALERT"\nMessage from HBM %s\n", msgBuffer);
    printk(KERN_ALERT".......... RETURN VALUE ...... : %d", ret_val);

    int Reg_Dev(void);
    memset (&sinfo, 0, sizeof(struct siginfo));
    sinfo.si_signo = SIGUSR1;
    sinfo.si_code  = SI_USER;

    if (id == 0) {
        printk("\ncan't find User PID: %d\n", id);
    }else {
    //task = pid_task(find_vpid(pid), PIDTYPE_PID);
    task = find_task_by_vpid(id);
    send_sig_info(SIGUSR1, &sinfo, task);
    }
    return 0;
}

static int device_open(struct inode *inode, struct file *file){
    /*sucess*/
    return 0;
}

void strPrint(void) {
    printk("value of msgBuffer: %s", msgBuffer);
}

static int device_write(struct file *file, const char *gdata, size_t len, loff_t *off){
    get_user (id,(int *)gdata);
    if(id <0)
        printk(KERN_ALERT"Cann't find PID from userspace its : %i", id);
    else
        printk(KERN_ALERT"Successfully received the PID of userspace %i", id);
    return len;
}

static int
device_read(struct file *file, char *buf, size_t len, loff_t *off){
    /*success*/
    return 0;
}

static int device_release(struct inode *inode, struct file *file){
    /*success*/
    return 0;
}


static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {


    switch (cmd) {
        case MESSAGTOUSER:
            ret_val = copy_to_user((char *)arg, msgBuffer, sizeof(arg));
            printk("Msg of Kernel %s", msgBuffer);
            break;
        default:
            break;
    }
    return 0;

}



static struct file_operations fops = {
    .open = device_open,
    .write = device_write,
    .read = device_read,
    .release = device_release,
    .unlocked_ioctl = device_ioctl
};


int Reg_Dev(void) {

    major_no = register_chrdev(0, "safe_dev", &fops);
    safe_class = class_create(THIS_MODULE, "safe_dev");
    device_create(safe_class,NULL, MKDEV(major_no, 0), "safe_dev");
    printk("\n Device Registered and Created \n");
    return 0;
}

void UnReg_dev (void) {
    printk("\nUser PID : %d\n", id);
    unregister_chrdev(major_no, "safe_dev");
    device_destroy(safe_class, MKDEV(major_no,0));
    class_unregister(safe_class);
    class_destroy(safe_class);
    printk("\n Device Un-Registered and Destroyed \n");
}

extern int Reg_Dev(void);

对于他的用户空间我有这个代码:

#define PORT 9930
#define G_IP "192.168.10.71"
#define BUFLEN 512

#define MESSAGTOUSER 0

unsigned char *str[20];
char b1[BUFLEN], b2[BUFLEN];
struct sockaddr_in me,client;
int s, i, n=sizeof(me);
int fd;



void error_handler(char *s) {
  perror(s);
  exit(1);
}



void signal_handler (int signum) {

  if(signum == SIGUSR1)
  {
    printf("\n%s\n",str);

    if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))  == -1)
       error_handler("\nERROR: in Socket\n");

    memset((char *) &me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_port = PORT;

    if (inet_aton(G_IP, &me.sin_addr)==0) 
    {
       fprintf(stderr, "inet_aton() failed\n");
       exit(1);
    }
    printf("Message from Kernel : %s", &str);
    //strcpy (str, newStr);


    int cntr =0;    sprintf(b2, "\nFailure Message: %s\n",str);
    printf("\nsending Fault to PMN Group : Tick - %d\n", cntr++);


    if(sendto(s, str, sizeof(str),0,(struct sockaddr *) &me,n)==-1)
        error_handler("\nERROR: in sendto()\n");
    close (s);
//    counter ++;
 //   sendAndReceiveOverUDP();
    return;
  }
}

int main() {
   pid_t u_id;
   u_id = getpid();
   int i = 1;

   fd = open("/dev/safe_dev",O_RDWR);
   write(fd, &u_id, 4);
   ioctl (fd, MESSAGTOUSER, &str);
   printf("\n PID sent to device successfully: %d \n", u_id);
   close(fd);

   signal(SIGUSR1, signal_handler);
   printf("\nMy PID is: %d\n",u_id);
   //printf("Subnet 1 working fine.. Tick - %d", tv.tv_sec);

   while (1)
   sleep(1);
   return 0;
}

现在我希望在用户空间上收到什么:

Message from Kernel: A<->B
Sending Fault o PMN Group : tick - 0

Message from Kernel: B<->B
Sending Fault o PMN Group : tick - 1
....
...

但是输出是什么:

Message from Kernel:
Sending Fault o PMN Group : tick - 0

Message from Kernel:
Sending Fault o PMN Group : tick - 1
....
...

似乎copy_to_user无法正常工作,而在简单程序中只是将一个字符串从内核复制到用户工作正常,但是当我在这个场景中使用它然后它无法正常工作时,它的编译没有任何警告,

  • 其他一些细节:
  • failureDetection()正在获取其他程序输出中提到的字符串A&lt; - &gt; B ..
  • 来自failureDetection的相同消息是在内核级别打印,但不在用户级别进行传输。
  • 我也尝试在此创建一个自己的字符串,并试图转移它,但它也无法正常工作!假设 msgBuffer = HI ,那么我应该收到HI到用户空间。但它没有发生!任何人都可以请这个代码让我纠正错误吗?如何才能获得用户空间的更新!! ??

娜斯迪胡..

2 个答案:

答案 0 :(得分:0)

copy_to_user()只会在响应ioctl()时发生,msgBuffer只会在您的代码中很早发生一次。据推测,此时内核缓冲区failureDetection()为空,因为failureDetection()函数尚未在该点运行。如果msgBuffer稍后运行并设置ioctl()并不重要,因为您的用户空间程序从不再次调用msgBuffer,因此它看不到copy_to_user()的新内容

您的sizeof(args)电话中也有错误 - 而不是4(这是一个常数sizeof msgBuffer),您应该使用{{1}}。

答案 1 :(得分:0)

@caf:非常感谢你......

void signal_handler (int signum) {

if(signum == SIGUSR1)
{
    fd = open ("/dev/safe_dev",O_RDWR);
    ioctl (fd, MESSAGTOUSER, &str);
    close (fd);

    if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))  == -1)
        error_handler("\nERROR: in Socket\n");

    memset((char *) &me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_port = PORT;

    if (inet_aton(G_IP, &me.sin_addr)==0) 
    {
        fprintf(stderr, "inet_aton() failed\n");
        exit(1);
    }

    printf("Failure Detected on Eth Cards as : %s are non reachable.", str);

    printf("\nsending Fault to PMN Group : Tick - %d\n", cntr++);
    sprintf(b2, "\nFailure Message: %s\n",str);



    if(sendto(s, str, sizeof(str),0,(struct sockaddr *) &me,n)==-1)
        error_handler("\nERROR: in sendto()\n");
    close (s);
    return;
    }
}

我只是犯了一个愚蠢的错误..呵呵......我没有在文件打开和关闭块之间添加它...你的建议解决了我的问题......

非常感谢您的回复..

<强> Rahee ..