靈修分享:亞略巴古的演講

亞略巴古的演說是使徒行傳一篇非常著名的講道。基督徒往往用這段經文來說明上帝的屬性,同時也會參考這段經文作為和外邦人互動的一個參考方式。最近因為團契查經查到這一段,重新思想後看到了以前沒有考慮過的面向,在這邊記錄一下。

徒17:16-34保羅在雅典等候他們的時候,看見滿城都是偶像,就心裏着急;於是在會堂裏與猶太人和虔敬的人,並每日在市上所遇見的人,辯論。還有伊壁鳩魯和斯多亞兩門的學士,與他爭論。有的說:「這胡言亂語的要說甚麼?」有的說:「他似乎是傳說外邦鬼神的。」這話是因保羅傳講耶穌與復活的道。他們就把他帶到亞略‧巴古,說:「你所講的這新道,我們也可以知道嗎?因為你有些奇怪的事傳到我們耳中,我們願意知道這些事是甚麼意思。」(雅典人和住在那裏的客人都不顧別的事,只將新聞說說聽聽。)
保羅站在亞略‧巴古當中,說:「眾位雅典人哪,我看你們凡事很敬畏鬼神。我遊行的時候,觀看你們所敬拜的,遇見一座壇,上面寫着『未識之神』。你們所不認識而敬拜的,我現在告訴你們。創造宇宙和其中萬物的神,既是天地的主,就不住人手所造的殿,也不用人手服事,好像缺少甚麼;自己倒將生命、氣息、萬物,賜給萬人。他從一本本:有古卷是血脈造出萬族的人,住在全地上,並且預先定準他們的年限和所住的疆界,要叫他們尋求神,或者可以揣摩而得,其實他離我們各人不遠;我們生活、動作、存留,都在乎他。就如你們作詩的,有人說:『我們也是他所生的。』我們既是神所生的,就不當以為神的神性像人用手藝、心思所雕刻的金、銀、石。世人蒙昧無知的時候,神並不監察,如今卻吩咐各處的人都要悔改。因為他已經定了日子,要藉着他所設立的人按公義審判天下,並且叫他從死裏復活,給萬人作可信的憑據。」
眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」於是保羅從他們當中出去了。 但有幾個人貼近他,信了主,其中有亞略‧巴古的官丟尼修,並一個婦人,名叫大馬哩,還有別人一同信從。

對基督徒來說,保羅這篇講道講的真好,不但講出了上帝的超越性(像是不住人手所造的殿、也不是金銀石的彫刻),也帶出了耶穌基督復活的大能。但最近我才注意到眾人的反應:「眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」」不曉得你看到這一段有什麼感想?可能我是玻璃心吧,如果我是保羅,我大概會非常非常的難過,看起來似乎沒有人理會這個福音、這篇講道。這篇被基督…

Linked List in Linux Kernel

Linklist 是最常被使用的一種資料結構,當然在 Link Kernel 中也不例外。下面會介紹在 Linux Kernel 中所使用的 Link List。 當然,按照慣例,排版會按照自己喜歡的格式來進行排 版。

Kernel: 2.6.17

在 Linux 裡面,List 的相關定義函式是放在 linux/include/linux/list.h,而最主要的定義如下:

struct list_head
{
struct list_head *next;
struct list_head *prev;
};

很明顯地可以看出,這是一個 double linked list 的架構,但是看起來跟一般我們寫程式所實作的方式並不相同。如果是我們設計的話,我們可能會設計成這個樣子:

struct my_list
{
void *myitem;
struct my_list *next;
struct my_list *prev;
};

其中 myitem 就是用來存每個 list node 的 Data ,而且為了要泛用,所以使用了 (void *) 這樣的資料型態。 這樣的設計跟 Linux Kernel 的設計到底有什麼差異還不清楚,或許是個人風格吧~
(我同事有發表相關的意見,他認為用 Linux Kernel 的那種作法可以將 list 跟 data 完全的切割,而使用我一般的作法,固然可以達到 list 的效果,但是在參數傳遞上,變數名稱將會是 struct my_list,而無法直覺的看出來實際的資料型態...well ...見仁見智囉)

Linux Kernel list 的使用方式,我們看下面一個範例:

#include < stdio.h >
#include < stdlib.h >
#include "list.h"

struct kool_list
{
int to;
struct list_head list;
int from;
};

int main(int argc, char **argv)
{
struct kool_list *tmp;
struct list_head *pos, *q;
unsigned int i;
struct kool_list mylist;

INIT_LIST_HEAD(&mylist.list);

for(i=5; i!=0; --i)
{
tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
printf("enter to and from:");
scanf("%d %d", &tmp->to, &tmp->from);
list_add(&(tmp->list), &(mylist.list));
}
printf("\n");

printf("traversing the list using list_for_each()\n");
list_for_each(pos, &mylist.list)
{
tmp= list_entry(pos, struct kool_list, list);
printf("to= %d from= %d\n", tmp->to, tmp->from);
}
printf("\n");

printf("traversing the list using list_for_each_entry()\n");
list_for_each_entry(tmp, &mylist.list, list)
{
printf("to= %d from= %d\n", tmp->to, tmp->from);
}
printf("\n");

printf("deleting the list using list_for_each_safe()\n");
list_for_each_safe(pos, q, &mylist.list)
{
tmp= list_entry(pos, struct kool_list, list);
printf("freeing item to= %d from= %d\n", tmp->to, tmp->from);
list_del(pos);
free(tmp);
}

return 0;
}

這段程式是一個非常簡單的範例,從 data structure 的宣告,到 list 的初始化,新增、刪除全都具備了,而 mylist 在這裡則是當作 dummy header。至於詳細 API or MACRO 的定義請在 linux/include/linux/list.h 自己查詢。下面只介紹我覺得有趣的寫法。

當我們使用 Linux Kernel 裡面的 list 時,也就是自訂一個 Data Structure ,並在裡面使用 list 時,我該如何透過該 list 的節點,取得整個 Data Structure 的內容呢?當然,從上述的範例得知,我們可以使用 list_entry 這個 MACRO,但他是怎麼做到的?先來看看定義:

#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

非常好,我們要再繼續追下去,搜尋的節果發現, container_of 這 MACRO 位在 linux/include/linux/kernel.h 裡面。定義如下:

/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

相當有趣的寫法~ 以上面我們所定的 struct kool_list 為例,我們可以用下圖來表示:


+-----------------+ ^
+ to + + offset
+-----------------+ <---- ptr
+ list_head +
+-----------------+
+ from +
+-----------------+


所以將 ptr 剪去 offset,就是真正資料的位置。

PS 1:
在 Kernel 2.4 的年代, list_entry 的實際作法如下(精神一樣)
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

PS 2:
offsetof 是 C99 新制定的 MACRO,定義如下:
"The offsetof() macro returns the offset of the element name within the struct or union composite. This provides a portable method to determine the offset."

PS 3:
typeof 也是一個常用的 MACRO,用法跟 sizeof 差不多,只是回傳值是輸入變數的型態,下面是一個簡單的範例。

#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

如何利用 Wireshark 來監聽 IEEE 802.11 的管理封包