posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          CSAPP上的例子,但是書中的源碼有問題,修改后的版本:
          #include "csapp.h"
          #define MAXARGS 128

          void eval(char *cmdline);
          int parseline(char *buf, char **argv);
          int buildin_command(char **argv);

          int main()
          {
              
          char cmdline[MAXLINE];

              
          while (1)
              {
                  printf(
          "");
                  Fgets(cmdline, MAXLINE, stdin);
                  
          if (feof(stdin))
                      exit(
          0);

                  eval(cmdline);
              }
          }

          void eval(char *cmdline)
          {
              
          char *argv[MAXARGS];
              
          char buf[MAXLINE];
              
          int bg;
              pid_t pid;

              strcpy(buf, cmdline);
              bg 
          = parseline(buf, argv);
              
          if (argv[0== NULL)
                  
          return;

              
          if (!builtin_command(argv))
              {
                  
          if ((pid = Fork()) == 0)
                  {
                      
          if (execve(argv[0], argv, environ) < 0)
                      {
                          printf(
          "%s: Command not found.\n", argv[0]);
                          exit(
          0);
                      }
                  }
                  
                  
          if (!bg)
                  {
                      
          int status;
                      
          if (waitpid(pid, &status, 0< 0)
                          unix_error(
          "waitfg: waitpid error");
                  }
                  
          else
                      printf(
          "%d %s", pid, cmdline);
              }
              
          return;
          }

          int builtin_command(char **argv)
          {
              
          if (!strcmp(argv[0], "quit"))
                  exit(
          0);
              
          if (!strcmp(argv[0], "&"))
                  
          return 1;
              
          return 0;
          }

          int parseline(char *buf, char **argv)
          {
              
          char *delim;
              
          int argc;
              
          int bg;

              buf[strlen(buf) 
          - 1= ' ';
              
          while (*buf && (*buf == ' '))
                  buf
          ++;

              argc 
          = 0;
              
          while ((delim = strchr(buf, ' ')))
              {
                  argv[argc
          ++= buf;
                  
          *delim = '\0';
                  buf 
          = delim + 1;
                  
          while (*buf && (*buf == ' '))
                      buf
          ++;
              }
              argv[argc] 
          = NULL;

              
          if (argc == 0)
                  
          return 1;

              
          if ((bg = (*argv[argc - 1== '&')) != 0)
                  argv[
          --argc] = NULL;

              
          return bg;
          }


          posted @ 2007-08-28 15:37 ZelluX 閱讀(636) | 評論 (0)編輯 收藏

               摘要: http://www.defmacro.org/ramblings/fp.html還是放在Mathematics類吧 Functional Programming For The Rest of Us Monday, June 19, 2006 Introduction Programmers are procrastinators. Get in, get some coffee, ...  閱讀全文

          posted @ 2007-08-24 22:54 ZelluX 閱讀(438) | 評論 (0)編輯 收藏

          1. dup和dup2函數
          #include <unistd.h>
          int dup(int filedes);
          int dup2(int filedes, int filedes2);
          // Both return: new file descriptor if OK, -1 on error

          dup返回的file descriptor(以下簡稱fd)為當前可用的最低號碼,dup2則指定目的fd,如果該fd已被打開,則首先關閉這個fd。
          dup后兩個fd指向相同的file table entry,這意味著它們共享同一個的file status flag, read, write, append, offset等。

          事實上,dup等價于
          fcntl(filedes, F_DUPFD, 0);

          dup2和也類似于
          close(filedes2);
          fcntl(filedes, F_DUPFD, filedes2);
          但這不是一個原子操作,而且errno也有一定的不同。

          posted @ 2007-08-22 15:46 ZelluX 閱讀(369) | 評論 (0)編輯 收藏

          Appending to a File
           考慮某個單一進程試圖在文件追加寫入的操作。由于早期的UNIX系統不支持O_APPEND選項,因此得先用lseek將offset置于文件尾部。
          if (lseek(fd, 0L, 2) < 0)
              err_sys("lseek error");
          if (write(fd, buf, 100) != 100)
              err_sys("write error");
          注意這里的lseek函數的第三個參數2等于SEEK_END常量,但是早期UNIX并沒有這個常量名(System V中才引進)

          這樣的處理在多進程試圖在同一文件尾部追加寫入時就有可能出現問題。
          假設兩個獨立線程A B要在某個文件尾部追加寫入,使用了上述方法,并沒有使用O_APPEND開關。
          首 先A指向了該文件尾部(假設是offset=1500的地方),接著內核切換到B進程,B也指向了該尾部,然后寫入了100字節,此時內核把v-node 中當前文件的大小改為了1600。內核再次切換進程,A繼續運行,調用write方法,結果就在offset=1500的地方寫入了,覆蓋了B進程寫入的 內容。

          這個問題其實和Java中的多線程差不多,指向文件尾部和寫入應該作為一個原子操作執行,就像Java中使用synchronized塊保護原子操作。使用O_APPEND選項就是一種解決方法。
          另一種解決方法時使用XSI extension中的pread和pwrite函數。
          #include <unistd.h>

          ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);
          // Returns: number of bytes read, 0 if end of file, -1 on error

          ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
          // Returns: number of bytes read, 0 if end of file, -1 on error

          調用pread與調用lseek后再調用read等價,以下情況除外:
          1. pread的兩個步驟無法被中斷。
          2. 文件指針尚未被更新時。

          pwrite與lseek+write的差別也相似。

          Creating a File
          當使用O_CREAT和O_EXCL開關調用open函數時,如果文件已經存在,則open函數返回失敗值。如果不使用這兩個開關,可以這樣寫:
          if ((fd = open(pathname, O_WRONLY)) < 0) {
              
          if (errno == ENOENT) {
                  
          if ((fd = creat(pathname, mode)) < 0)
                      err_sys(
          "creat error");
              } 
          else {
                  err_sys(
          "open error");
              }
          }

          當open函數執行后creat函數執行前另一個進程創建了同名文件的話,該數據就會被擦除。

          posted @ 2007-08-21 14:45 ZelluX 閱讀(524) | 評論 (0)編輯 收藏

          內核使用三種數據結構表示一個打開的文件,他們之間的關系決定了進程間對于共享文件的作用。
          Every process has an entry in the process table. Within each process table entry is a table of open file descriptors, which we can think of as a vector, with one entry per descriptor. Associated with each file descriptor are
          1) The file descriptor flags (close-on-exec; refer to Figure 3.6 and Section 3.14)
          2) A pointer to a file table entry

          The kernel maintains a file table for all open files. Each file table entry contains
          1) The file status flags for the file, such as read, write, append, sync, and nonblocking
          2) The current file offset
          3) A pointer to the v-node table entry for the file

          Each open file (or device) has a v-node structure that contains information about the type of file and pointers to functions that operate on the file. For most files, the v-node also contains the i-node for the file. This information is read from disk when the file is opened, so that all the pertinent information about the file is readily available. For example, the i-node contains the owner of the file, the size of the file, pointers to where the actual data blocks for the file are located on disk, and so on.


          上圖為這三種數據結構及其相互聯系
          其中v-node主要用于提供單個操作系統上的多文件系統支持,Sun把它稱為Virtual File System
          linux中沒有v-node,使用了一個generic i-node代替,盡管使用了不同的實現方式,v-node在概念上與generic i-node相同。

          下面來討論兩個獨立的進程打開同一文件的情況
          這種情況下兩個進程擁有不同的file table,但其中的兩個指針指向了同一個v-node。

          知道了這些數據結構的情況以后,我們可以更精確的知道某些操作的結果
          1) 每次write操作結束后,當前文件的offset增加,如果這個操作導致當前的offset超出了文件長度,則i-node表中記錄的文件大小會被修改為改動后的大小。
          2) 使用O_APPEND方式打開文件后,每次調用write函數時,當前文件的offset都會被設置為i-node表中的該文件大小,從而write函數只能在文件尾部追加。
          3) lseek 函數只改變在file table中的當前文件offset,并不會產生io操作

          注意file descriptor flag和file status flag的作用域差別,前者屬于某個單獨進程的單獨的file descriptor,后者則適用于任意進程中指向給定file table entry的所有descriptor。fcntl函數可以修改這兩種flag

          posted @ 2007-08-20 22:39 ZelluX 閱讀(641) | 評論 (0)編輯 收藏

          1. 貌似和dive into python中的有一定的差異,可能是版本的關系(python 2.2 - 2.5)
          minidom.parse("binary.xml")得到的對象是binary.xml的整棵dom樹,它的第一個結點包含了DOCTYPE的相關信息,對于它的字節點的firstNode,貌似一般都是空的。

          2. unicode 相關
          string.encode()
          sys.getdefaultencoding()
          指定.py文件編碼的方法:
          在每個文件開頭加入編碼聲明
          # -*- coding: UTF-8 -*-

          3. python目錄的lib/site-packages/sitecustomize.py是一個特殊的腳本,Python會在啟動的時候導入它。

          4. 搜索元素:
          getElementByTagName()
          返回的是一個list

          5. 元素屬性
          attributes 是一個xml.dom.minidom.NameNodeMap實例,常用的方法如keys() values(),同時也有__getitem__方法,類似于dictionary

          posted @ 2007-08-18 16:33 ZelluX 閱讀(1128) | 評論 (0)編輯 收藏

          居然要軍訓兩星期后才搬去張江,殘念啊。。。
          求到了個代理,總算能上外網,卻上不了TopCoder
          在寢室百無聊賴ing...

          算了,還是看會兒書吧

          posted @ 2007-08-17 22:33 ZelluX 閱讀(346) | 評論 (1)編輯 收藏

          1. 幾個常用對象:
          os.system  執行命令
          sys.stdin  sys.stdout
          os.path.getsize   獲得文件大小
          os.path.isdir
          os.mkdir
          os.listdir

          2. walk()函數
          很好用的一個函數
          os.path.walk(rootdir, f, arg)
          rootdir是要訪問的目錄樹的根,f是用戶定義的函數,arg是調用f時用的一個參數。
          對于每一個"walk"過程中遇到的目錄directory,設該目錄下的文件列表為filelist,walk函數會調用
          f(arg, directory, filelist)

          posted @ 2007-08-15 22:34 ZelluX 閱讀(374) | 評論 (0)編輯 收藏

          ? super T 語法將泛型類限制為所有T的超類(包括T自身),但只能用于參數中,不可以在返回值用加以限定。
          如果不加以限定,假設某個函數頭為
          ? super Manager get()
          由于編譯器不知道該方法究竟會返回什么類,這樣就只能用Object類來接收了。

          該語法常用的一個情況是泛型類的比較
          java.util.TreeSet<E> 代表一個有序的元素為E的樹,它其中的一個構造器需要一個Comparator類來比較兩個元素,以E為String類時為例,此時的Comparator可以是Comparator<String>,也可以是Comparator<Object>,但Comparator<Integer>就不行,如何表示這樣的限制呢?
          jdk源代碼中是這樣的:
          public TreeSet(Comparator<? super E> c)
          這樣就保證了傳給構造器的Comparator是可以進行E元素的比較的。

          另一個例子,java.util.Collections的max方法用于獲得一個容器中的最大值,這個函數頭可以這樣寫:
          public static <T extends Comparable<T>>  T max(Collection<T> coll)

          這樣就限定T為能和自己比較的類,過于嚴格,jdk源碼是這樣的:
          public static <extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
              Iterator
          <? extends T> i = coll.iterator();
              T candidate 
          = i.next();

              
          while(i.hasNext()) {
              T next 
          = i.next();
              
          if (next.compareTo(candidate) > 0)
                  candidate 
          = next;
              }

              
          return candidate;
          }

          很嚴謹的函數頭,但是限定方面比較寬

          posted @ 2007-08-15 15:51 ZelluX 閱讀(6562) | 評論 (0)編輯 收藏

          1. 交換x和y的值  [x, y] = [y, x]

          2. zip()方法把幾個lists的第i個元素合成一個tuple,放在一個新的list中。
          zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

          函數式編程相關

          1.  Mapping
          map() 方法對序列中的每個元素調用某個函數,返回新生成的結果序列。
          有點類似于Ruby的Array.each do | element |
          >>> z = map(len, ["abc", "clounds", "rain"])
          >>> z
          [3, 6, 4]

          2. Filtering
          過濾掉滿足條件的元素,類似與Array.reject do | element |
          >>> x = [5,12,-2,13]
          >>> y = filter(lambda z: z > 0, x)
          >>> y
          [5, 12, 13]

          3. List Comprehension
          來個復雜的例子
          >>> y
          [[0, 2, 22], [1, 5, 12], [2, 3, 33]]
          >>> [a for b in y for a in b[1:]]
          [2, 22, 5, 12, 3, 33]

          4. Reduction
          先看示例
          >>> x = reduce(lambda x,y: x+y, range(5))
          >>> x
          10
          執行的順序是:首先調用函數處理range(5)前兩個值,0 + 1 = 1,然后返回的值1作為x,繼續與range(5)的第三個值(2,作為y)。
          最后的結果是0+1+2+3+4的值
          這個常用來代替for循環

          posted @ 2007-08-15 00:07 ZelluX 閱讀(402) | 評論 (0)編輯 收藏

          僅列出標題
          共39頁: First 上一頁 15 16 17 18 19 20 21 22 23 下一頁 Last 
          主站蜘蛛池模板: 榕江县| 崇义县| 壤塘县| 英山县| 南和县| 西吉县| 通山县| 龙陵县| 巴楚县| 报价| 阿坝| 凤山市| 泾川县| 视频| 兴国县| 玉环县| 大丰市| 阿图什市| 平南县| 利川市| 扎兰屯市| 乐东| 泗洪县| 沅江市| 荆门市| 收藏| 象山县| 德安县| 淳化县| 龙江县| 高邮市| 新昌县| 蒙城县| 庆元县| 张家口市| 嫩江县| 泰来县| 斗六市| 亚东县| 百色市| 台州市|