如何摆脱内核编程中的分段错误?
How do I get rid of segmentation fault in kernel programming?
我在进行内核编程时遇到段错误。我创建了一个名为 process_list 的字符设备。尝试从设备读取时出现分段错误。
导致分段错误的代码部分,即 dev_read() 如下:
static ssize_t dev_read(struct file *filep, char *user_buffer, size_t len, loff_t *offset)
{
int error_count=0;
if(error_count < 0)
{
return error_count;
}
for_each_process(task)
{
if (task->state == 0){snprintf(state_str,200,"%s", "TASK_RUNNING");}
else if (task->state == 1){snprintf(state_str,200,"%s", "TASK_INTERRUPTIBLE");}
else if (task->state == 2){snprintf(state_str,200,"%s", "TASK_UNINTERRUPTIBLE");}
else if (task->state == 4){snprintf(state_str,200,"%s", "__TASK_STOPPED");}
else if (task->state == 8){snprintf(state_str,200,"%s", "__TASK_TRACED");}
else if (task->state == 16){snprintf(state_str,200,"%s", "EXIT_DEAD");}
else if (task->state == 32){snprintf(state_str,200,"%s", "EXIT_ZOMBIE");}
else if (task->state == 64){snprintf(state_str, 200,"%s","TASK_DEAD");}
else if (task->state == 128){snprintf(state_str,200,"%s", "TASK_WAKEKILL");}
else if (task->state == 256){snprintf(state_str,200,"%s", "TASK_WAKING");}
else if (task->state == 512){snprintf(state_str,200,"%s", "TASK_PARKED");}
else if (task->state == 1024){snprintf(state_str, 200,"%s","TASK_NOLOAD");}
else if (task->state == 2048){snprintf(state_str,200,"%s", "TASK_NEW");}
else if (task->state == 4096){snprintf(state_str,200,"%s", "TASK_STATE_MAX");}
else if (task->state == (16 | 32)){snprintf(state_str, 200,"%s", "EXIT_ZOMBIE , EXIT_DEAD");}
else if (task->state == (128 | 2)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , TASK_UNINTERRUPTIBLE");}
else if (task->state == (128 | 4)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , __TASK_STOPPED");}
else if (task->state == (128 | 8)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , __TASK_TRACED");}
else if (task->state == (2 | 1024)){snprintf(state_str, 200,"%s", "TASK_UNINTERRUPTIBLE , TASK_NOLOAD");}
else if (task->state == (1 | 2)){snprintf(state_str, 200,"%s", "TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE");}
else if (task->state == (0 | 1 | 2 | 4 | 8 | 32 |16)){snprintf(state_str, 200,"%s", "TASK_RUNNING , TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE , __TASK_STOPPED , __TASK_TRACED , EXIT_ZOMBIE , EXIT_DEAD");}
else if (task->state == (1 | 2 | 4 | 8)){snprintf(state_str, 200,"%s", "TASK_NORMAL , __TASK_STOPPED , __TASK_TRACED");}
else {snprintf(state_str,200,"%s", "OTHER");}
sprintf(kernel_buffer + strlen(kernel_buffer), "PID=%d PPID=%d CPU=%d STATE=%s\n", task->pid, task->real_parent->pid, task_cpu(task),state_str);
size_of_buffer = strlen(kernel_buffer);
}
error_count = copy_to_user(user_buffer, kernel_buffer, size_of_buffer);
return error_count;
}
如果 kernel_buffer
没有在某处初始化(它没有显示在发布的代码片段中)那么 strlen(kernel_buffer)
可以在内存中永远继续寻找空字符(零字节),走关闭有效映射内存的末尾。
建议使用 case 语句代替许多嵌套 'if else'。不是答案,但风格会更好。
我在进行内核编程时遇到段错误。我创建了一个名为 process_list 的字符设备。尝试从设备读取时出现分段错误。 导致分段错误的代码部分,即 dev_read() 如下:
static ssize_t dev_read(struct file *filep, char *user_buffer, size_t len, loff_t *offset)
{
int error_count=0;
if(error_count < 0)
{
return error_count;
}
for_each_process(task)
{
if (task->state == 0){snprintf(state_str,200,"%s", "TASK_RUNNING");}
else if (task->state == 1){snprintf(state_str,200,"%s", "TASK_INTERRUPTIBLE");}
else if (task->state == 2){snprintf(state_str,200,"%s", "TASK_UNINTERRUPTIBLE");}
else if (task->state == 4){snprintf(state_str,200,"%s", "__TASK_STOPPED");}
else if (task->state == 8){snprintf(state_str,200,"%s", "__TASK_TRACED");}
else if (task->state == 16){snprintf(state_str,200,"%s", "EXIT_DEAD");}
else if (task->state == 32){snprintf(state_str,200,"%s", "EXIT_ZOMBIE");}
else if (task->state == 64){snprintf(state_str, 200,"%s","TASK_DEAD");}
else if (task->state == 128){snprintf(state_str,200,"%s", "TASK_WAKEKILL");}
else if (task->state == 256){snprintf(state_str,200,"%s", "TASK_WAKING");}
else if (task->state == 512){snprintf(state_str,200,"%s", "TASK_PARKED");}
else if (task->state == 1024){snprintf(state_str, 200,"%s","TASK_NOLOAD");}
else if (task->state == 2048){snprintf(state_str,200,"%s", "TASK_NEW");}
else if (task->state == 4096){snprintf(state_str,200,"%s", "TASK_STATE_MAX");}
else if (task->state == (16 | 32)){snprintf(state_str, 200,"%s", "EXIT_ZOMBIE , EXIT_DEAD");}
else if (task->state == (128 | 2)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , TASK_UNINTERRUPTIBLE");}
else if (task->state == (128 | 4)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , __TASK_STOPPED");}
else if (task->state == (128 | 8)){snprintf(state_str, 200,"%s", "TASK_WAKEKILL , __TASK_TRACED");}
else if (task->state == (2 | 1024)){snprintf(state_str, 200,"%s", "TASK_UNINTERRUPTIBLE , TASK_NOLOAD");}
else if (task->state == (1 | 2)){snprintf(state_str, 200,"%s", "TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE");}
else if (task->state == (0 | 1 | 2 | 4 | 8 | 32 |16)){snprintf(state_str, 200,"%s", "TASK_RUNNING , TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE , __TASK_STOPPED , __TASK_TRACED , EXIT_ZOMBIE , EXIT_DEAD");}
else if (task->state == (1 | 2 | 4 | 8)){snprintf(state_str, 200,"%s", "TASK_NORMAL , __TASK_STOPPED , __TASK_TRACED");}
else {snprintf(state_str,200,"%s", "OTHER");}
sprintf(kernel_buffer + strlen(kernel_buffer), "PID=%d PPID=%d CPU=%d STATE=%s\n", task->pid, task->real_parent->pid, task_cpu(task),state_str);
size_of_buffer = strlen(kernel_buffer);
}
error_count = copy_to_user(user_buffer, kernel_buffer, size_of_buffer);
return error_count;
}
如果 kernel_buffer
没有在某处初始化(它没有显示在发布的代码片段中)那么 strlen(kernel_buffer)
可以在内存中永远继续寻找空字符(零字节),走关闭有效映射内存的末尾。
建议使用 case 语句代替许多嵌套 'if else'。不是答案,但风格会更好。