2012-04-09 19 views
11

Tôi đang phát triển một mô-đun hạt nhân sử dụng unlocked_ioctl. Tôi đã thử nghiệm nó với phiên bản kernel 2.6.24-23-generic và nó hoạt động hoàn hảo. Bây giờ tôi đã thử nó với phiên bản kernel 3.3.1-1-ARCH và một cái gì đó kỳ lạ xảy ra: chức năng ioctl không được thực hiện khi giá trị yêu cầu (cmd) là 2. Nó trả về 0, nhưng chức năng không được thực hiện. Để kiểm tra xem nó không được thực hiện tôi đã làm như sau:ioctl không được gọi nếu cmd = 2

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

printk("Called with cmd = %d\n", cmd); 

Tôi đã viết một chương trình thử nghiệm mà các cuộc gọi ioctl cho thiết bị này 0-4096, và tôi có thể nhìn thấy trong dmesg thông báo "gọi với cmd = n "cho tất cả các giá trị đó, ngoại trừ" 2 ", giá trị duy nhất không được hiển thị.

Bất kỳ manh mối nào về những gì tôi đang làm sai?

Cảm ơn bạn trước,

+0

Một số mã lên trong chuỗi được chặn cmd == 2 và xử lý nó? – zvrba

Trả lời

9

Hãy xem trên this:

546 int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, 
547    unsigned long arg) 
548 { 
549  int error = 0; 
550  int __user *argp = (int __user *)arg; 
551  struct inode *inode = filp->f_path.dentry->d_inode; 
552 
553  switch (cmd) { 
554  case FIOCLEX: 
555    set_close_on_exec(fd, 1); 
556    break; 
557 
558  case FIONCLEX: 
559    set_close_on_exec(fd, 0); 
560    break; 
561 
562  case FIONBIO: 
563    error = ioctl_fionbio(filp, argp); 
564    break; 
565 
566  case FIOASYNC: 
567    error = ioctl_fioasync(fd, filp, argp); 
568    break; 
569 
570  case FIOQSIZE: 
571    if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || 
572     S_ISLNK(inode->i_mode)) { 
573      loff_t res = inode_get_bytes(inode); 
574      error = copy_to_user(argp, &res, sizeof(res)) ? 
575          -EFAULT : 0; 
576    } else 
577      error = -ENOTTY; 
578    break; 
579 
580  case FIFREEZE: 
581    error = ioctl_fsfreeze(filp); 
582    break; 
583 
584  case FITHAW: 
585    error = ioctl_fsthaw(filp); 
586    break; 
587 
588  case FS_IOC_FIEMAP: 
589    return ioctl_fiemap(filp, arg); 
590 
591  case FIGETBSZ: 
592    return put_user(inode->i_sb->s_blocksize, argp); 
593 
594  default: 
595    if (S_ISREG(inode->i_mode)) 
596      error = file_ioctl(filp, cmd, arg); 
597    else 
598      error = vfs_ioctl(filp, cmd, arg); 
599    break; 
600  } 
601  return error; 
602 

Như bạn thấy, có một số các switch-trường hợp trước khi vfs_ioctl hoặc file_ioctl gọi.

+0

Tôi không thấy mức độ liên quan, không trường hợp nào trong số này áp dụng – Hasturkun

+1

Tôi đã sửa chữa, giá trị của 'FIGETBSZ' thực tế là 2, +1 – Hasturkun

3

Như được chỉ ra bởi @Ilya, Bạn đang gặp trường hợp chung (FIGETBSZ trong trường hợp này).

Nói chung, bạn muốn soạn lệnh ioctl bằng cách sử dụng _IO family of macros, với một loại duy nhất, để tránh va chạm.

tôi khuyên bạn nên đọc ioctl-number.txt từ tài liệu hạt nhân cho biết thêm thông tin, bao gồm một danh sách các hầu hết các loại đã qua sử dụng

+0

Đây là ví dụ tối thiểu' ioctl' sử dụng '_IOx': https: // stackoverflow .com/a/44613896/895245 –