2015-11-07 20 views
5

Tôi đã viết một cuộc gọi hệ thống tùy chỉnh cho một nhiệm vụ so sánh hai số nguyên và trả về số nguyên lớn nhất. Dưới đây là mã của tôi kernel-side (max.c):Linux - Tại sao cuộc gọi hệ thống tùy chỉnh hoạt động không đúng với số âm?

#include <linux/kernel.h> 
#include <linux/syscalls.h> 

asmlinkage long sys_max(int num1, int num2) 
{ 
    if (num1 > num2) 
    { 
    return num1; 
    } 

    else 
    { 
    return num2; 
    } 
} 

Và đây là mã của tôi sử dụng không gian (max.h):

#include <unistd.h> 
#define SYS_MAX 323 

int max(int num1, int num2) 
{ 
    int maxnumber = syscall(SYS_MAX, num1, num2); 
    return maxnumber; 
} 

Tôi đang sử dụng chương trình này ít để kiểm tra hệ thống gọi:

#include <stdio.h> 
#include <max.h> 

int main() 
{ 
    int a, b; 
    scanf("%d", &a); 
    scanf("%d", &b); 
    printf("%d", max(a, b)); 
    return 0; 
} 

Nó hoạt động tốt cho số dương hoặc khi dương và âm kia, nhưng luôn trả về -1 khi xử lý hai giá trị âm. Tôi đã tự hỏi liệu điều này có phải là do chuyển đổi dài hay không, nhưng dường như tôi không thể hiểu được nguyên nhân gây ra vấn đề.

+0

'int max (int num1, int num2) {}' - đó là định nghĩa hàm chứ không phải khai báo. Ý bạn là 'int max (int, int);'? – melpomene

+0

Có gì thay đổi nếu bạn đổi tên hàm 'max' thành' mymax' không? – melpomene

+0

@melpomene Tiếng Anh không phải là ngôn ngữ mẹ đẻ của tôi, vì vậy tôi không chắc đó là từ thích hợp ở đây. Nhưng vấn đề là hàm max phải trả về một số nguyên và nhận hai số nguyên làm tham số. –

Trả lời

10

Nếu cuộc gọi hệ thống trả về giá trị âm, nó được coi là lỗi và mã xử lý lỗi đặc biệt được gọi trong libc. Cụ thể, giá trị trả lại bị phủ nhận và được chuyển vào biến số toàn cầu errno và giá trị trả về của cuộc gọi hệ thống trở thành -1.

Thực ra, khi đọc về điều này, tôi phát hiện ra rằng trên Linux, only values from -4095 to -1 are treated as errors, nhưng đây không phải là di động, cũng không hữu ích nếu bạn muốn chức năng của bạn hoạt động trên mọi giá trị có thể.

Tóm lại, bạn không thể sử dụng giá trị trả về của syscall một cách an toàn để trả lại giá trị có thể âm. Quy ước thông thường sẽ là chuyển một con trỏ tới một biến đích để giữ kết quả và dự trữ mã trả về thành công/thất bại. Lưu ý rằng khi thực hiện điều này với một syscall, bạn sẽ làm việc với một con trỏ không gian người dùng từ không gian hạt nhân, do đó, cần có copy_to_user để ghi kết quả.

+0

Cảm ơn rất nhiều vì nỗ lực và câu trả lời. Tôi gặp sự cố khi triển khai các hàm copy_to_user và copy_from_user. Bất kỳ lời khuyên nào về cách thực hiện điều đó? –

+0

@ BernardoLopes đó là một câu hỏi khác và câu hỏi mà tôi không thể trả lời tốt. Tìm kiếm câu trả lời và nếu bạn không thể tìm ra câu hỏi, hãy đặt câu hỏi mới trên SO :) – hobbs

+0

Cảm ơn, tôi sẽ thử với mã mới. Tôi sẽ báo cáo lại khi nó kết thúc biên dịch. –

Các vấn đề liên quan