В настоящее время я делаю системный вызов, который объединяет несколько файлов в один на уровне ядра.
Распечатав количество байтов, скопированных в сообщениях ядра, и проверив выходной файл, я вижу, что я может успешно объединить файлы в выходной файл.
Однако, когда мой системный вызов (xmerge. c) завершается и возвращается к моему пользовательскому пространственному коду (test_xmerge. c) для тестирования моего пользовательского системный вызов, происходит ошибка сегментации.
Ошибка, которую я получаю, когда "tail -50 / var / log / messages" выглядит следующим образом:
Кажется, что системный вызов не может вернуть количество общих байтов обратно в пространство пользователя (вернуть итог;), что вызывает ошибку сегментации в коде тестирования пространства пользователя.
Однако такой проблемы не возникает, когда система вызов возвращает код ошибки (return -EFAULT;), поскольку я могу распечатать возвращаемое значение в test_xmerge без ошибки сегментации.
Мой код для xmerge. c выглядит следующим образом:
//For xmerge.c placed in the linux-4.19.105/os-lab
#include <a bunch of includes>
struct xmerge_params{
char __user *outfile; // name of the output file
char __user **infiles; // array with names of input files
unsigned int num_files; // number of input files
int oflags; // the open flag for the outfile
mode_t mode; // default permission mode for newly created outfile
int __user *ofile_count; // it will be updated as the number of files that have been read into outfile
};
SYSCALL_DEFINE2(xmerge, void*, args, size_t, argslen){
struct xmerge_params ps;
# Omit a bunch of variable init
if (copy_from_user(&ps, args, argslen) != 0){
printk(KERN_INFO "Cannot Copy From User\n");
return -EFAULT; // This return -EFAULT would not cause segmentation fault
}
outfile = ksys_open(ps.outfile, ps.oflags, ps.mode);
if (outfile < 0) {
return outfile; // This return outfile would not cause segmentation fault
}
for (i = 0; i < ps.num_files; i++){
# Omit the file copying using buffer
*(ps.ofile_count)++;
}
ksys_close(outfile);
printk(KERN_INFO "Total: %d\n", total);
set_fs(old_fs);
if (copy_to_user(args, &ps, argslen) != 0){
printk(KERN_INFO "Cannot Copy To User\n");
return -EFAULT;
}
printk(KERN_INFO "Finish Syscall, total: %d\n", total);
return total; // Unable to return total
}
Для кода тестирования test_xmerge. c:
#include <a bunch of includes>
struct xmerge_params{
char *outfile; // name of the output file
char **infiles; // array with names of input files
unsigned int num_files; // number of input files
int oflags; // the open flag for the outfile
mode_t mode; // default permission mode for newly created outfile
int *ofile_count; // it will be updated as the number of files that have been read into outfile
};
int main(int argc, const char *argv[]){
# Omit a bunch of variable init
int flag;
while ((flag = getopt(argc, argv, "actem:h")) != -1){
switch (flag){
# Omit dealing with the command line arguments
}
}
# Omit setting up xmerge_params
ps.ofile_count = (int*)malloc(100 * sizeof(int)); // Added this line fixed the segmentation problem
*(ps.ofile_count) = 0;
printf("Before call syscall\n");
printf("*(ps.ofile_count)%d\n", *(ps.ofile_count)); // Value is 0
res = syscall(SYSCALL_NUM_XMERGE, &ps, sizeof(struct xmerge_params));
printf("*(ps.ofile_count)%d\n", *(ps.ofile_count)); // Value should be 2 but still output 0
printf("After call syscall\n");
if (res >= 0){
printf("%d bytes from %d files are copied\n", res, *(ps.ofile_count));
} else{
printf("Error: %i %s\n", errno, strerror(errno));
}
return 0;
}
Может кто-нибудь помочь мне разобраться в проблеме? Так как я пытался выяснить проблему в течение нескольких дней, и отладка это раздражает, когда каждый раз, когда я хочу попробовать некоторые модификации, которые я должен сделать; делать модули; make modules_install; сделать установку. И подождите, пока он соберется и скомпилируется в течение 10 минут на моей виртуальной машине.
Обновление: после дальнейшей отладки я обнаружил, что проблема в том, что я не выделил память в test_xmerge. c для ps.ofile_count, и когда я увеличиваю ps.ofile_count в xmerge, я хочу увеличивать адрес, а не значение. Вот почему это вызвало ошибку сегментации.
Проблема сегментации была исправлена. Но возникла другая проблема: copy_to_user, похоже, не работает для ps.ofile_count. ie, когда я выводил ps.ofile count после итерации для l oop в xmerge, он выводится как 2 (так как у меня есть два файла для слияния). Однако, когда я вывожу его в test_xmerge после системного вызова, значение ps.ofile_count остается равным 0. Таким образом, кажется, что copy_to_user foes работает, поскольку значение ps.ofile_count не обновляется.
I удалили old_fs = get_fs () ;, set_fs (get_ds ()); и set_fs (old_fs); строка до и после copy_to_user. Но это не решает проблему.
Есть идеи, почему это происходит и как это исправить?