c - 要求成员'tv_sec'不在某种结构或 union 中。''系统调用linux

标签 c linux linux-kernel system-calls

我正在尝试添加一个新的系统调用,该调用显示有关进程的一些信息。我创建了一个名为processinf的新结构,它包含我要显示的部分进程信息。下面是在types.h中定义的processinf代码

struct processinf
{
    pid_t pid;
    long state;
    char *comm;
    time_t st;
};

系统调用:
#include <linux/sched.h>
#include <linux/linkage.h>
#include <linux/pid.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/time.h>


asmlinkage long proc_inf(pid_t pid, struct processinf *p)
{
    struct task_struct *task = pid_task(find_vpid(pid), PIDTYPE_PID);
    p->pid = task->pid;
    strcpy(p->comm, task->comm);
    p->state = task->state;
    p->st = task->start_time.tv_sec;


    copy_to_user(p, p, sizeof(struct processinf));
    return 0;
}

当我尝试使用make构建内核时,会得到以下错误:
错误:请求成员“tv\u sec”的内容不是结构或联合
p->st=task->start_time.tv_秒;
我错过了什么?

最佳答案

这个问题的性质和所呈现的代码强烈地表明,即使在目前这种能力下,您也没有做好做内核工作的准备。如果你只是在自学,我强烈建议你把注意力放在用户空间上。如果这是一个大学作业,看起来是,我必须问你提供了什么材料,特别是你从哪里取得代码样本。由于同样的错误和相似性质的问题在手头出现了很多,我怀疑有人只是给出了非常糟糕的学习材料。
在问题下面添加了两条评论。我发现他们的质量很低,如果不是直接有害的。
第一个正确地指出copy_to_user(p,p,…);可能是错误的。但是,它包含一个非常令人费解的语句,建议“strcpy(p->comm,task->comm);-->p->comm=strdup(task->comm);”。
第二个建议是查看task结构,以确定开始时间的类型。更好的做法是寻找已经存在的代码来读取字段。
尽管这些考虑都无关紧要,因为代码存在根本性的缺陷,但上述评论未能解决这个问题。
让我们看看代码:

asmlinkage long proc_inf(pid_t pid, struct processinf *p)

首先,请注意'p'通常用作指向线程的指针的名称,因此在这里看到它有些混乱。我建议改名为“pi”。
{
    struct task_struct *task = pid_task(find_vpid(pid), PIDTYPE_PID);

linux内核是一个多线程的项目在这样的环境中,访问各种对象需要遵循某些规则。这样做可以保证以一致的状态读取数据,并且目标对象不会被突然释放。不遵守规则很容易导致在足够的负载下崩溃。这一点从您希望获得的并发编程课程中应该是显而易见的。
特别是,线程可以随时创建和销毁(和释放)。因此,如果您要访问一个随机线程,您需要一种方法来确保它不会被释放,直到您不再需要它。
呈现的代码一定是错的。任务以某种方式被固定返回,但您在结束时未能将其固定,或者任务未被固定,并且您未能首先满足调用pid_task的要求。碰巧是后者。具体要求留给读者作为练习。
    p->pid = task->pid;

可能未找到任务,指针为空。
“p”是用户空间提供的指针。这种方式的访问是一种安全性和可靠性威胁。考虑当用户在内核中传递某个地址或是垃圾时会发生什么。另外,在某些情况下(例如SMAP或内核地址空间与用户空间分离的体系结构),它也会直接失效。
这种方式的事情应该在课程开始时就已经涉及到了。
    strcpy(p->comm, task->comm);

基本编程问题。与以前的情况类似,您应该检查现有用户如何访问该字段,这将导致您“
获取任务通信。此外,您会发现“comm”字段是TASK_comm_LEN字符长,修改结构使其具有大小数组而不是指针可能是非常有意义的。
    p->state = task->state;
    p->st = task->start_time.tv_sec;

一个小小的奇怪来自命名上的差异——所有其他字段的名称都与task结构中的名称一致,但这一个不同。目前还不清楚在确定字段类型以及如何访问字段时存在什么问题。
你要找的一个很好的工具是“grep”。
    copy_to_user(p, p, sizeof(struct processinf));

现在这条线让事情变得更奇怪。如果你意识到你必须把东西复制出来,并且要复制到p所指的内存中,为什么你之前要取消对p的引用?正如评论中提到的,这显然是错误的。
您需要的是struct processinf类型的局部变量,将其填充,然后将其复制出来。
最后,copy_to_用户很容易失败,错误应该传播回用户,而不是被忽略。
    return 0;
}

关于c - 要求成员'tv_sec'不在某种结构或 union 中。''系统调用linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41067608/

相关文章:

在 C 中将大端转换为小端 [不使用提供的函数]

c - 实现一个小型图书馆

python - Stty 疯狂地使用 Python 子进程

c - 让 : *** No rule to make target 'all' . 停止。 C/C++问题

Linux 内核多核问题

c - 字符串或文件熵

ios - 重定向提交到调度队列的 block

c - CMSG_ALIGN 宏的值是多少

linux - linux下打开的文件是什么?

linux - 最大进程数和最大 PID 值