2013年8月11日 星期日

read() system call

http://debug-sai.blogbus.com/logs/51711788.html

asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
//傳入文件fd
 struct file *file;
 ssize_t ret = -EBADF;
 int fput_needed;
//根據文件fd得到file
 file = fget_light(fd, &fput_needed);
 if (file) {
  //讀出當前偏移
  loff_t pos = file_pos_read(file);
  //從當前偏移讀,pos返回讀取後的偏移
  ret = vfs_read(file, buf, count, &pos);
  //設置新偏移
  file_pos_write(file, pos);
  fput_light(file, fput_needed);//
 }
 return ret;
}
看看fget_light是怎麼根據fd得到file的
struct file *fget_light(unsigned int fd, int *fput_needed)
{
 struct file *file;
 struct files_struct *files = current->files;
 *fput_needed = 0;
 if (likely((atomic_read(&files->count) == 1))) {
//若已經打開了
  file = fcheck_files(files, fd);
 } else {
//若沒有打開,加鎖
  rcu_read_lock();
  file = fcheck_files(files, fd);
  if (file) {
   if (atomic_long_inc_not_zero(&file->f_count))
    *fput_needed = 1;
   else
    /* Didn't get the reference, someone's freed */
    file = NULL;
  }
  rcu_read_unlock();
 }
 return file;

fput_light的流程如下,具體見源代碼:
fput_light->fput(當所有釋放完時還要調用__fput)
接著看 vfs_read:
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
 ssize_t ret;
 //下面都是一系列驗證
 if (!(file->f_mode & FMODE_READ))
  return -EBADF;
 if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
  return -EINVAL;
 if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
  return -EFAULT;
 ret = rw_verify_area(READ, file, pos, count);
 if (ret >= 0) {
  count = ret;
 
  if (file->f_op->read)
   //一般都是到這裡調用vfs的read
   ret = file->f_op->read(file, buf, count, pos);
  else
   ret = do_sync_read(file, buf, count, pos);
  if (ret > 0) {
   fsnotify_access(file->f_path.dentry);
   add_rchar(current, ret);
  }
  inc_syscr(current);
 }
 return ret;
}
跟著就是vfs設置的read函數了,對於ext2來說是
const struct file_operations ext2_file_operations = {
 .llseek  = generic_file_llseek,
 .read  = do_sync_read,
 .write  = do_sync_write,
 .aio_read = generic_file_aio_read,
 .aio_write = generic_file_aio_write,
 .unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
 .compat_ioctl = ext2_compat_ioctl,
#endif
 .mmap  = generic_file_mmap,
 .open  = generic_file_open,
 .release = ext2_release_file,
 .fsync  = ext2_sync_file,
 .splice_read = generic_file_splice_read,
 .splice_write = generic_file_splice_write,
};
所以是do_sync_read:
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
 struct iovec iov = { .iov_base = buf, .iov_len = len };
 struct kiocb kiocb;
 ssize_t ret;
 //初始化kiocb
 init_sync_kiocb(&kiocb, filp);
 kiocb.ki_pos = *ppos;
 kiocb.ki_left = len;
 for (;;) {
  //其實就是變了個參數傳到generic_file_aio_read中。。。具體分析就先到這了
  ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
  if (ret != -EIOCBRETRY)
   break;
  wait_on_retry_sync_kiocb(&kiocb);
 }
 if (-EIOCBQUEUED == ret)
  ret = wait_on_sync_kiocb(&kiocb);
 *ppos = kiocb.ki_pos;
 return ret;
}

2013年8月9日 星期五

[review] Brownfield Application Development in .NET

說在前頭,這是一本好書,還有我不懂C#, .NET  XD

簡而言之,作者相信,好的軟體流程跟設計是一切的根本,如果專案失控,大致上是這兩方面出問題,所以一書分成兩個部分,第一部分先談到brownfield application的定義,跟著提出軟體流程的工具,比方說VCS、Testing、Defect...等等,如何使用,第二部分則是設計模式跟原則,基本上遵循design pattern的兩句話,low coupling high cohesion & design for interface。

衍生出來的就很多,比方說IoC、DI...,書中主要反應在兩種設計方式上,一個是MVP,另外一個是Anticorruption layer

Anticorruption layer
因應第三方元件或者其他需求,在每一層可以考慮加入一個layer,發揮類似seam的作用,讓上下層依賴這個介面,也就是Robert C. Martin所謂的
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
每一層可以獨立作業,也不會類似過去TCP/IP的設計方式,每一層依賴於下一層,每一層都可以獨立發展

效果類似於下圖
圖片中綠色的區塊相當等於seam的部分SpellChecker跟SpellCheckDictionary可以分開獨立發展,中間接合的部分,由ISpellCheckDictionary承擔,有MVP的味道

2013年8月4日 星期日

javascript loading的考量

javascript loading有些必須考量的點,比方載入方式、相依性、模組化、最佳化

方式

1. 直接使用script tag的src屬性
2. 使用document.write方式動態載入
3. 自行產生DOM元素加入
4. 使用AJAX動態取得
現在web browser通常使用aysnchronous載入,最佳化性能,但是有時必須考慮相依性

相依性

javascript loading相依性上有RequireJS來處理,一來可以解決相依性,二來可以只載入必要的元素即可

模組化

而引入的javascript通常可以視為一個模組,一個好的模組必須符合一些規範,如AMD,而CommonJS正是這樣的概念下的RIA framework

最佳化

而javascript載入有時取決於script tag的位置,變數名稱以及檔案形式。好比將tag至於文件尾端,讓DOM Tree儘快生成,產生頁面,但是副作用是有時script產生的動態元素會比較慢呈現在網頁上。為了讓javascript parser比較快讀取產生,使用如google closure compiler,縮短變數名稱等等動作,可以讓javascript產生較好的效能,但是會犧牲程式的可讀性

參考資料:

https://developers.google.com/closure/compiler/?hl=zh-TW
http://josephj.com/entry.php?id=349
http://www.jb51.net/article/17992.htm
http://ithelp.ithome.com.tw/question/10120521?tag=rss.qu
http://tc.itkee.com/developer/detail-1a9a.html
http://www.puritys.me/docs-blog/article-160

2013年8月1日 星期四

[review] MVP

之前在網路上搜尋MVP的時候,無意看到有人說MVC更適合web application這種stateless的開發,非常違反我直覺地描述,最近終於發現可能得出處,是一本書

Brownfield Application Development in .NET,中文翻譯:軟體構築美學

先說違反直覺的部分,首先MVC提出非常早,遠早於現在流行的web application,也就是說MVC一開始是為了application設計才對,以這種觀點,application大多屬於有狀態的(state),很少是stateless

作者有幾點小小的誤會,首先MVC架構定義跟傳統不大一樣,可以參考POSA一書對MVC架構的描述,MVP不是Martin Folwer提出來的,首先是由IBM於1997年左右提出的,Martin Folwer的MVP算是IBM的改良版本,這種誤解有點類似Martin Folwer提出了refactoring的概念是一樣的,不過Martin Folwer是一個總結並且發揚光大的人是肯定的,非原本名詞的提出者,一點都不損及Martin Folwer的地位

撇開這個不講,書中對各種模型的描述倒是很清楚,如Passive View、Supervising Controller、MVC、MVP

為了觀察web application,先考慮過去MVC是由誰驅動?大多是由應用程式建立了一堆view之後,再由view引發事件驅動controller,可是在web appliction,卻是由網頁直接接觸controller,然後再產生新的view(網頁)

因為stateless以及web流程的特性,controller變成了進入點,再加上route的概念盛行,controller工作變成了,如何引導流程,且非由view創立出來的,所以整體的角色改變了

再者MVC本身有個小小的缺點,view本身是認知model的存在(耦合性),這有一點點暴露風險的部分是,程式設計師會直接透過view去操作model,而非controller,此外view往往為了model必須要修改,無法獨力發展

MVP有效的解決這問題,首先view直接獨立發展,畫面更新等等事情交由presenter去考慮,model本身從前就已經很獨立了,現在更加地不用透過類似observer patter去通知view,耦合更少。在view與model都獨立的狀況下,必須有角色負責媒合兩者,那個就是presenter,而presenter必須利用IoC的概念,引入兩者view跟model(有可能有很多view與很多model instances),作為媒介
可是這時候,一些事件的傳遞要如何作用?在web application上面,這件事情不是很嚴重,因為server直接扮演了controller以及route腳色,如同第一個MVC圖片一樣,只是現在將MVC中的MV改成了MVP,但是在應用程式上呢?所以才有上面的application controller存在。

這裡可能會冒出的疑問是,那麼model跟view之間的耦合性不見了,那麼如何更新view?由presenter,但是presenter也無法知道model有沒有更新阿!?Martin Folwer告訴我們,如果要達到主動更新只好把類似observer pattern再放到model跟presenter身上,耦合性又回來了XD天下沒有白吃的午餐,不過透過MVP,讓view與model可以獨立發展,大大提高view的resue了