2016-12-09 16 views
0

プロセスに関するいくつかの情報を表示する新しいシステムコールを追加しようとしています。私は表示したいプロセス情報の一部を含むprocessinfという名前の新しい構造体を作成しました。ここでtypes.hで``構造体や共用体ではないメンバー 'tv_sec'の要求 ``システムコールlinux

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

、システムコールで定義されてprocessinfコードは次のとおりです。

#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; 
} 

私は、私は次のエラーを取得します使用してカーネルを構築しよう: エラー:メンバーのリクエスト "を構造体または共用体でないものの中のtv_sec ' p-> st = task-> start_time.tv_sec; 私はここで何が欠けていますか?

+0

おそらく 'p-> comm'は割り当てられたスペースを指していません。 '' '' '' '' '' '' '' '' '' '' '' '' '' ''はstrcpy(p-> comm、task-> comm)ドギーも - 自己にコピー? – chux

+0

'struct task_struct'の定義を探します。そこに 'start_time'メンバがあります。その 'start_time'メンバは、' struct timespec'または 'struct timeval'(' tv_sec'メンバを含む2つの標準POSIX型)ではありません。 '.'の代わりに' - > 'が必要な場合や、' time_t'が非構造体の場合など、別の型にポインタを移動することもできます。 'struct task_struct'の定義で、これを解決するのは簡単です。それなしでは、それを解決することは不可能です。 –

答えて

1

この質問の性質と提示されたコードは、現時点でこの容量であってもカーネルの作業を行うことができないことを強く示唆しています。あなた自身だけで学習しているのであれば、ユーザー空間に焦点を当てて一歩前進することを強くお勧めします。これが大学の授業であれば、どのような資料を提供したか、特にコードサンプルをどこから入手したのかを尋ねる必要があります。非常に同じ間違いや手に似た性質の質問が多く出てくるので、誰かが非常に悪い学習教材を出してくれると思う。

質問の下に2件のコメントが追加されています。まっすぐに有害でないならば、私はそれらが低品質であることがわかります。

最初のものは正当にcopy_to_user(p、p、..);おそらく間違っているでしょう。しかし、それは "strcpy(p-> comm、task-> comm); - > p-> comm = strdup(task-> comm);という非常に不思議な声明を含んでいます。

第2のものは、task_structを見て、start_timeのタイプが何であるかを調べることを提案します。代わりに行うべきもっと良いことは、フィールドを読み取っている既存のコードを探すことです。

コードに根本的な欠陥がありますが、これらのコメントは問題に対処できません。

はのコードを見てみましょう:

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; 

タスクが見つからず、ポインタがNULLである可能性があります。

'p'はユーザー空間によって提供されるポインタです。この方法へのアクセスはセキュリティと信頼性の脅威です。ユーザーがカーネル内の何かのアドレスを渡すか、ガベージであるときに何が起こるかを考えてください。また、いくつかのケース(例えば、SMAPや、ユーザ空間から分割されたカーネルアドレス空間を持つアーキテクチャ)ではまっすぐに動作しません。

このようなことは、コースの始めにカバーされているはずです。

strcpy(p->comm, task->comm); 

基本的なプログラミングの問題。以前のケースと同様に、既存のコンシューマがどのようにフィールドにアクセスしているかを確認すると、 ' get_task_comm'につながります。さらに、 'comm'フィールドの長さはTASK_COMM_LENであり、ポインタの代わりにサイズの配列を持つように構造体を変更するのが理にかなっています。

p->state = task->state; 
    p->st = task->start_time.tv_sec; 

小さなすごみは、ネーミングの格差から来ている - 他のすべてのフィールドは、task_structに発見されたものと一致名前を持っているが、これは発散します。また、フィールドのタイプとそのフィールドへのアクセス方法を調べることで、何が問題であるかは非常に不明です。

あなたが探している素晴らしいツールの1つが「grep」です。

copy_to_user(p, p, sizeof(struct processinf)); 

この行では、さらに奇妙なものになります。あなたが物事をコピーしなければならないことを知っていて、pによって指し示されたメモリに、なぜ以前に 'p'を参照解除していたのですか?コメントで述べたように、これは明らかに間違っていなければなりません。

必要なものは、struct processinf型のローカル変数です。それを埋め込み、次にそれをコピーします。

最後に、copy_to_userは簡単に失敗する可能性があり、エラーは無視されるのではなくユーザーに伝播されます。

return 0; 
} 
関連する問題