2016-04-15 70 views
1

以下代碼循環遍歷curr_task的祖先,一直到swapper進程(即任何Linux進程的「最遠的」祖先),因爲swapper == swapper->parent會停止。循環進程的父母,Linux內核

while (curr_task != curr_task->parent) 
     ...get curr_task info 
     curr_task = curr_task->parent 

問題是我也想得到swapper過程的信息。有幾個明顯的方法可以做到這一點(例如,while循環之後的goto語句,或獲得swapper信息的循環之後的單個if語句)。但是,這些明顯的解決方案看起來相當不雅,所以我正在尋找一個更簡潔的解決方案,不涉及嚴重錯誤的goto或複製/粘貼代碼。

回答

2

下面是做到這一點的一種方法:使用另一個變量。

struct task_struct *t, *prev; 
t = current; 
do { 
    // do something with t 
    prev = t; 
    t = t->parent; 
} while (prev->pid != 0); 

或移動到一個函數:

int move_up(struct task **tp) { 
    int was_swapper = ((*tp)->pid == 0); 
    *tp = (*tp)->parent; 
    return was_swapper; 
} 

// ... 

struct task_struct *t = current; 
do { 
    // do something with t 
} while (move_up(&t)); 
+0

另外:如果有這樣的事情,這將是一個「反向逗號運算符」的可愛應用程序:像逗號運算符,除了它的值是第一個操作數而不是第二個操作數。例如,如果':'是一個這樣的操作符,那麼我們可以在(t:t = t-> parent);'時寫'do {...}。 –

2

使用一些功能來做到這一點如下。

walk_tasks_backwards_from(current); 

功能遵循...

static void walk_tasks_backwards_from(struct task_struct *pos); 
static void process_tasks(struct task_struct *parent, struct task_struct *child); 

static void process_tasks(struct task_struct *parent, struct task_struct *child) { 
    pr_alert("parent process: %s, PID: %d\n", parent->comm, parent->pid); 
    pr_alert("child process: %s, PID: %d\n", child->comm , child->pid); 
} 

static void walk_tasks_backwards_from(struct task_struct *pos) { 
    struct task_struct *parent; ; 
    do { 
    parent = pos->parent; 
    process_tasks(parent, pos); 
    pos = parent; 
    } while(parent->pid != 0); 
} 

您可以使用您想從即

walk_tasks_backwards_from(current); 

走電流或任何任務時,這會產生我的機器,其中以下輸出調用函數我有一個玩具內核模塊,可以使用cat /dev/toy

[161769.300609] parent process: bash, PID: 918 
[161769.301299] child process: cat, PID: 2803 
[161769.301973] parent process: login, PID: 626 
[161769.302632] child process: bash, PID: 918 
[161769.303216] parent process: systemd, PID: 1 
[161769.303797] child process: login, PID: 626 
[161769.304355] parent process: swapper/0, PID: 0 
[161769.304978] child process: systemd, PID: 1 

另外,您可以使用以下任何...

使用do {} while

task = current;// Get current process 
printk(KERN_INFO "process: %s, PID: %d", task->comm, task->pid); 
do { 

    task = task->parent; 
    printk(KERN_INFO "process: %s, PID: %d", task->comm, task->pid); 

} while (task->pid != 0); 
//task here has pid == 0; 

或使用while循環。

task = current;// Get current process 
while (task->pid != 0) { 

    printk(KERN_INFO "process: %s, PID: %d", task->comm, task->pid); 
    task = task->parent; 

} 
//task here has pid == 0; 
printk(KERN_INFO "process: %s, PID: %d", task->comm, task->pid); 

遍歷一切

struct task_struct task; 
for_each_process(task) { 
    printk(KERN_INFO "process: %s, PID: %d", task->comm, task->pid); 
} 
+0

這將跳過當前的任務雖然 – Adam

+0

它不會跳過當前的任務。您可以將'printk'移動到'task = task-> parent'的上方或下方。代碼放在塊中由你決定。我將把printk放在它上面,這樣你就可以看到我的意思了。 – Harry

+0

@哈利:現在它不打印任何交換。 –