2017年1月25日 星期三

Linux C Read GPS Data From UART


Linux C Read GPS data from UART

1.使用Terminal終端機介面(TTY),讓Linux系統透過UART串列埠連接GPS。終端機介面有二種模式:正規(canonical)模式和非正規(non-canonical=raw input)模式。
模式 說明


  • 正規(canonical)模式: 終端設備會處理特殊字元,且會以一次一列的方式將輸入傳給應用程式。

正規模式
原文
Canonical Input 
Canonical input is line-oriented. Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received. 
When selecting this mode you normally select the ICANONECHO, and ECHOE options: 
    options.c_lflag |= (ICANON | ECHO | ECHOE);

  • 非正規(non-canonical)模式:又稱為raw模式。在這種模式中,終端設備不會處理特殊字元,且會以一次一個字元的方式將輸入傳給應用程式。           
非正規
原文
Raw Input
Raw input is unprocessed. Input characters are passed through exactly as they are received, when they are received. Generally you'll deselect the ICANONECHOECHOE, and ISIG options when using raw input: 
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

2.開啟通訊埠
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define MODEMDEVICE "/dev/ttyS2"

...

   fd = open(MODEMDEVICE, O_RDWR|O_NOCTTY|O_NDELAY ); 
   if (fd <0) {perror(MODEMDEVICE); exit(-1); }

...

3.Termios結構     
struct termios{
tcflag_t c_iflag;                    /*輸入模式*/
tcflag_t c_oflag;                   /*輸出模式*/
tcflag_t c_cflag;                   /*控制模式*/
tcflag_t c_lflag;                    /*局部模式*/
cc_t c_cc[NCCS];               /*特殊控制字元*/
}



Table : The c_iflag Member
ConstantDescription
INPCKEnable parity check
IGNPARIgnore parity errors
PARMRKMark parity errors
ISTRIPStrip parity bits
IXONEnable software flow control (outgoing)
IXOFFEnable software flow control (incoming)
IXANYAllow any character to start flow again
IGNBRKIgnore break condition
BRKINTSend a SIGINT when a break condition is detected
INLCRMap NL to CR
IGNCRIgnore CR
ICRNLMap CR to NL
IUCLCMap uppercase to lowercase
IMAXBELEcho BEL on input line too long



Table : The c_oflag Member
ConstantDescription
OPOSTPostprocess output (not set = raw output)
OLCUCMap lowercase to uppercase
ONLCRMap NL to CR-NL
OCRNLMap CR to NL
NOCRNo CR output at column 0
ONLRETNL performs CR function
OFILLUse fill characters for delay
OFDELFill character is DEL
NLDLYMask for delay time needed between lines
NL0No delay for NLs
NL1Delay further output after newline for 100 milliseconds
CRDLYMask for delay time needed to return carriage to left column
CR0No delay for CRs
CR1Delay after CRs depending on current column position
CR2Delay 100 milliseconds after sending CRs
CR3Delay 150 milliseconds after sending CRs
TABDLYMask for delay time needed after TABs
TAB0No delay for TABs
TAB1Delay after TABs depending on current column position
TAB2Delay 100 milliseconds after sending TABs
TAB3Expand TAB characters to spaces
BSDLYMask for delay time needed after BSs
BS0No delay for BSs
BS1Delay 50 milliseconds after sending BSs
VTDLYMask for delay time needed after VTs
VT0No delay for VTs
VT1Delay 2 seconds after sending VTs
FFDLYMask for delay time needed after FFs
FF0No delay for FFs
FF1Delay 2 seconds after sending FFs



Table : The c_cc Member
ConstantDescriptionKey
VINTRInterruptCTRL-C
VQUITQuitCTRL-Z
VERASEEraseBackspace (BS)
VKILLKill-lineCTRL-U
VEOFEnd-of-fileCTRL-D
VEOLEnd-of-lineCarriage return (CR)
VEOL2Second end-of-lineLine feed (LF)
VMINMinimum number of characters to read
VTIMETime to wait for data (tenths of seconds)

4.範例

4.1

Canonical Input Processing

        #include <sys/types.h>
        #include <sys/stat.h>
        #include <fcntl.h>
        #include <termios.h>
        #include <stdio.h>

        /* baudrate settings are defined in <asm/termbits.h>, which is
        included by <termios.h> */
        #define BAUDRATE B38400            
        /* change this definition for the correct port */
        #define MODEMDEVICE "/dev/ttyS2"
        #define _POSIX_SOURCE 1 /* POSIX compliant source */

        #define FALSE 0
        #define TRUE 1

        volatile int STOP=FALSE; 

        int main(int argc, char *argv[])
        {
          int fd,c, res;
          struct termios oldtio,newtio;
          char buf[255];
        /* 
          Open modem device for reading and writing and not as controlling tty
          because we don't want to get killed if linenoise sends CTRL-C.
        */
         fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
         if (fd <0) {perror(MODEMDEVICE); exit(-1); }
        
         tcgetattr(fd,&oldtio); /* save current serial port settings */
         bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */
        
        /* 
          BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
          CRTSCTS : output hardware flow control (only used if the cable has
                    all necessary lines. See sect. 7 of Serial-HOWTO)
          CS8     : 8n1 (8bit,no parity,1 stopbit)
          CLOCAL  : local connection, no modem contol
          CREAD   : enable receiving characters
        */
         newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
         
        /*
          IGNPAR  : ignore bytes with parity errors
          ICRNL   : map CR to NL (otherwise a CR input on the other computer
                    will not terminate input)
          otherwise make device raw (no other input processing)
        */
         newtio.c_iflag = IGNPAR | ICRNL;
         
        /*
         Raw output.
        */
         newtio.c_oflag = 0;
         
        /*
          ICANON  : enable canonical input
          disable all echo functionality, and don't send signals to calling program
        */
         newtio.c_lflag = ICANON;
         
        /* 
          initialize all control characters 
          default values can be found in /usr/include/termios.h, and are given
          in the comments, but we don't need them here
        */
         newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
         newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
         newtio.c_cc[VERASE]   = 0;     /* del */
         newtio.c_cc[VKILL]    = 0;     /* @ */
         newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
         newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
         newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
         newtio.c_cc[VSWTC]    = 0;     /* '\0' */
         newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
         newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
         newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
         newtio.c_cc[VEOL]     = 0;     /* '\0' */
         newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
         newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
         newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
         newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
         newtio.c_cc[VEOL2]    = 0;     /* '\0' */
        
        /* 
          now clean the modem line and activate the settings for the port
        */
         tcflush(fd, TCIFLUSH);
         tcsetattr(fd,TCSANOW,&newtio);
        
        /*
          terminal settings done, now handle input
          In this example, inputting a 'z' at the beginning of a line will 
          exit the program.
        */
         while (STOP==FALSE) {     /* loop until we have a terminating condition */
         /* read blocks program execution until a line terminating character is 
            input, even if more than 255 chars are input. If the number
            of characters read is smaller than the number of chars available,
            subsequent reads will return the remaining chars. res will be set
            to the actual number of characters actually read */
            res = read(fd,buf,255); 
            buf[res]=0;             /* set end of string, so we can printf */
            printf(":%s:%d\n", buf, res);
            if (buf[0]=='z') STOP=TRUE;
         }
         /* restore the old port settings */
         tcsetattr(fd,TCSANOW,&oldtio);
        }
        close(fd);
        return 0;
     }


4.2

Non-Canonical Input Processing

      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <termios.h>
      #include <stdio.h>
        
      #define BAUDRATE      B38400
      #define MODEMDEVICE   "/dev/ttyS2"
      #define _POSIX_SOURCE 1              /* POSIX compliant source */
      #define FALSE 0
      #define TRUE  1
        
      volatile int STOP=FALSE; 
       
      int main(int argc, char *argv[])
      {
        int fd,c, res;
        struct termios oldtio,newtio;
        char buf[255];
        
        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
        if (fd <0) {perror(MODEMDEVICE); exit(-1); }
        
        tcgetattr(fd,&oldtio); /* save current port settings */
        
        bzero(&newtio, sizeof(newtio));
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
        
        /* set input mode (non-canonical, no echo,...) */
        newtio.c_lflag = 0;
         
        newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
        newtio.c_cc[VMIN]     = 1;   /* blocking read until 5 chars received */
        
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
        
        
        while (STOP==FALSE) {       /* loop for input */
          res = read(fd,buf,255);   /* returns after 5 chars have been input */
          buf[res]=0;               /* so we can printf... */
          printf(":%s:%d\n", buf, res);
          if (buf[0]=='z') STOP=TRUE;
        }
        tcsetattr(fd,TCSANOW,&oldtio);
        close(fd);
        return 0;
      }//main



4.3

Asynchronous Input

      #include <termios.h>
      #include <stdio.h>
      #include <unistd.h>
      #include <fcntl.h>
      #include <sys/signal.h>
      #include <sys/types.h>
        
      #define BAUDRATE B38400
      #define MODEMDEVICE "/dev/ttyS1"
      #define _POSIX_SOURCE 1 /* POSIX compliant source */
      #define FALSE 0
      #define TRUE 1
        
      volatile int STOP=FALSE; 
        
      void signal_handler_IO (int status);   /* definition of signal handler */
      int wait_flag=TRUE;                    /* TRUE while no signal received */
        
      int main(int argc, char *argv[])
      {
        int fd,c, res;
        struct termios oldtio,newtio;
        struct sigaction saio;           /* definition of signal action */
        char buf[255];
        
        /* open the device to be non-blocking (read will return immediatly) */
        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd <0) {perror(MODEMDEVICE); exit(-1); }
        
        /* install the signal handler before making the device asynchronous */
        saio.sa_handler = signal_handler_IO;
        saio.sa_mask = 0;
        saio.sa_flags = 0;
        saio.sa_restorer = NULL;
        sigaction(SIGIO,&saio,NULL);
          
        /* allow the process to receive SIGIO */
        fcntl(fd, F_SETOWN, getpid());
        /* Make the file descriptor asynchronous (the manual page says only 
           O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
        fcntl(fd, F_SETFL, FASYNC);
        
        tcgetattr(fd,&oldtio); /* save current port settings */
        /* set new port settings for canonical input processing */
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR | ICRNL;
        newtio.c_oflag = 0;
        newtio.c_lflag = ICANON;
        newtio.c_cc[VMIN]=1;
        newtio.c_cc[VTIME]=0;
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
         
        /* loop while waiting for input. normally we would do something
           useful here */ 
        while (STOP==FALSE) {
          printf(".\n");usleep(100000);
          /* after receiving SIGIO, wait_flag = FALSE, input is available
             and can be read */
          if (wait_flag==FALSE) { 
            res = read(fd,buf,255);
            buf[res]=0;
            printf(":%s:%d\n", buf, res);
            if (res==1) STOP=TRUE; /* stop loop if only a CR was input */
            wait_flag = TRUE;      /* wait for new input */
          }
        }
        /* restore old port settings */
        tcsetattr(fd,TCSANOW,&oldtio);
        close(fd);
        return 0;
      }
        
      /***************************************************************************
      * signal handler. sets wait_flag to FALSE, to indicate above loop that     *
      * characters have been received.                                           *
      ***************************************************************************/
        
      void signal_handler_IO (int status)
      {
        printf("received SIGIO signal.\n");
        wait_flag = FALSE;
      }



4.4

Waiting for Input from Multiple Sources

      #include <sys/time.h>
      #include <sys/types.h>
      #include <unistd.h>
        
      int main(int argc, char *argv[])
      {
        int    fd1, fd2;  /* input sources 1 and 2 */
        fd_set readfs;    /* file descriptor set */
        int    maxfd;     /* maximum file desciptor used */
        int    loop=1;    /* loop while TRUE */ 
        
        /* open_input_source opens a device, sets the port correctly, and
           returns a file descriptor */
        fd1 = open_input_source("/dev/ttyS1");   /* COM2 */
        if (fd1<0) exit(0);
        fd2 = open_input_source("/dev/ttyS2");   /* COM3 */
        if (fd2<0) exit(0);
        maxfd = MAX (fd1, fd2)+1;  /* maximum bit entry (fd) to test */
        
        /* loop for input */
        while (loop) {
          FD_SET(fd1, &readfs);  /* set testing for source 1 */
          FD_SET(fd2, &readfs);  /* set testing for source 2 */
          /* block until input becomes available */
          select(maxfd, &readfs, NULL, NULL, NULL);
          if (FD_ISSET(fd1))         /* input from source 1 available */
            handle_input_from_source1();
          if (FD_ISSET(fd2))         /* input from source 2 available */
            handle_input_from_source2();
        }
        close(fd1);
        close(fd2);
        return 0;
      }   


The given example blocks indefinitely, until input from one of the sources becomes available. If you need to timeout on input, just replace the select call by:
        int res;
        struct timeval Timeout;

        /* set timeout value within input loop */
        Timeout.tv_usec = 0;  /* milliseconds */
        Timeout.tv_sec  = 1;  /* seconds */
        res = select(maxfd, &readfs, NULL, NULL, &Timeout);
        if (res==0)
        /* number of file descriptors with input = 0, timeout occurred. */ 


[參考]
1.http://blog.xuite.net/uwlib_mud/twblog/108242774-Linux+RS-232+程式設計
2.https://www.cmrr.umn.edu/~strupp/serial.html.
3.http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html

2016年6月29日 星期三

project 集中式管理: git 進階圖解

版本控制

project 集中式管理 - git 進階圖解篇













project 集中式管理


git版本控制管理分3種方式:1.中央式(集中式)管理2. 整合管理3.司令官與副手管理.(參考1)
由於開發專案需求;就使用git來做管理專案,順便把過程經驗記錄下來.本文開始先建立Remote端專案;透過兩位user(user1, user2)對專案的修改與更新來探討git集中式管理.

專案:prj_nvp.git

專案檔案已經加入git管理;放在server(以後git所謂的Remote,就是指server端的專案).

下載git Server的專案至本地(Local)

在Local PC上複製server上專案開始開發:
$ git clone ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git

Remote Server 與 Local PC

git clone下載後,預設分支(branch)叫master;而Remote端叫origin/master.

當Local端有更新的城市內容要上傳,使用command如下:
   $git push origin master

當origin有新的更新想下載,使用command如下:
   $git pull origin



<Note ***>
git pull origin相當於做了git fetch origin + git merge origin/master.


我們先探討進行專案更改後的後悔的挽救行為!


[git commit 之前]
1.將files變成staged
$git add .
2.將files從staged改成unstated : git reset HEAD <file> $git reset HEAD *

3.將file改爛後;想取回以前版本的source code: git checkout -- <file> $git checkout -- nvp6124.c

[git commit 之後]
/*砍掉前一個commit, ^代表前一個版本*/
$git reset HEAD^                    

/*提交後發現漏掉某些檔案,可這樣修改*/
$git commit -m "update xxx"
$git add some_file
$git commit --ament


<Note *>
目前操作都是以目前Local分支(branch)而言,也就是master.


探討push事件:user1 目前版本 5403ef8<--a60a684



$git push origin (請注意Remote端git權限問題,否則無法push)

...nvp_prj/prj_nvp$git push origin
warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

When push.default is set to 'matching', git will push local branches
to the remote branches that already exist with the same name.

In Git 2.0, Git will default to the more conservative 'simple'
behavior, which only pushes the current branch to the corresponding
remote branch that 'git pull' uses to update the current branch.

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)


‘matching’ 參數是 Git 1.x 的默認行為,其意是如果你執行 git push 但沒有指定分支,它將 push 所有你本地的分支到遠程倉庫中對應匹配的分支。而 Git 2.x 默認的是 simple,意味著執行 git push 沒有指定分支時,只有當前分支會被 push 到你使用 git pull 獲取的代碼.

設定下面條件後, 再次push時warning不見了:
$git config --global push.default matching

$git push origin   (出現其他錯誤)
root@rdfw:/home/paddy/workspace/nvp_prj/prj_nvp# git push origin
git@60.251.61.76's password: 
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 395 bytes | 0 bytes/s, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: error: insufficient permission for adding an object to repository database ./objects
remote: fatal: failed to write object
error: unpack failed: unpack-objects abnormal exit
To ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git'
root@rdfw:/home/paddy/workspace/nvp_prj/prj_nvp# git push origin
git@60.251.61.76's password: 
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 395 bytes | 0 bytes/s, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git
 ! [remote rejected] master -> master (branch is currently checked out)



這是由於git默認拒絕了push操作,需要進行設置,修改Remote端的.git/config添加如下代碼:

                 [receive]
                  denyCurrentBranch = ignore


$git push origin   (成功啦!)
root@rdfw:/home/paddy/workspace/nvp_prj/prj_nvp# git push origin
git@60.251.61.76's password: 
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 395 bytes | 0 bytes/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git
   5403ef8..a60a684  master -> master


<Note ***>
如果push後看不到commit的檔案;需做兩件事:
1. $vi .git/config添加如下代碼:

                 [receive]
                  denyCurrentBranch = ignore
2. $vi .git/post-receive
             #!/bin/sh
             GIT_WORK_TREE=/opt/git/project/prj_nvp.git git checkout -f

探討push事件:user2 目前版本 5403ef8<--506b929



$git push origin    (user2沒有執行 git pull origin, 就直接push出錯了)

...prj_nvp# git push origin
git@60.251.61.76's password: 
To ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'ssh://git@60.251.61.76:9022/opt/git/project/prj_nvp.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.



所以先pull將Remote端的更動merge進來
$git push origin   (= git fetch origin + git merge origin/master)
$git log                (merge後產生新的commit)
...nvp_issue21/prj_nvp$git pull origin
git@60.251.61.76's password: 
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From ssh://60.251.61.76:9022/opt/git/project/prj_nvp
   5403ef8..a60a684  master     -> origin/master
Merge made by the 'recursive' strategy.
 nvp6124_list.c | 9 +++++++++
 ohh.txt        | 0
 2 files changed, 9 insertions(+)
 create mode 100644 nvp6124_list.c
 create mode 100644 ohh.txt
root@rdfw:/home/paddy/workspace/nvp_issue21/prj_nvp# git log
commit be2c2028f081466f99343b440db6a1acd16df143
Merge: 506b929 a60a684
Author: super <super@gmail.com>
Date:   Tue Jun 28 17:11:54 2016 +0800

    Merge branch 'master' of ssh://60.251.61.76:9022/opt/git/project/prj_nvp

commit 506b929f3e7ff1cb6ee63d343bdb478141ca34e4
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 16:27:05 2016 +0800

    add user2_fix

commit a60a684add1a5aedf3a37946e27130b82a42d29d
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 16:19:25 2016 +0800

    update: nvp6124_list.c + ohh.txt

commit 5403ef8db220f97fced2f46100439ae003987548
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 12:07:06 2016 +0800

    Uploading source code



但是如果發現,工作上未做完或是有檔案忘記加入;需要取消上次push的commit,這時候先git log
觀察到先前commit:
           
commit be2c2028f081466f99343b440db6a1acd16df143
Merge: 506b929 a60a684

要把這個commit取消再push一次,此時要進行revert動作:
$git checkout master               //切換分支至master
$git revert -m 1 be2c2028f081466f99343b440db6a1acd16df143
...nvp_issue21/prj_nvp$git revert -m 1 be2c2028f081466f99343b440db6a1acd16df143
[master a2464ef] Revert "Merge branch 'master' of ssh://60.251.61.76:9022/opt/git/project/prj_nvp"
 2 files changed, 9 deletions(-)
 delete mode 100644 nvp6124_list.c
 delete mode 100644 ohh.txt


$git log


...nvp_issue21/prj_nvp$ git log
commit a2464efdba2cfc03116dabd1f05250d021f18585
Author: super <super@gmail.com>
Date:   Wed Jun 29 09:36:48 2016 +0800

    Revert "Merge branch 'master' of ssh://60.251.61.76:9022/opt/git/project/prj_nvp"
    
    This reverts commit be2c2028f081466f99343b440db6a1acd16df143, reversing
    changes made to 506b929f3e7ff1cb6ee63d343bdb478141ca34e4.

commit be2c2028f081466f99343b440db6a1acd16df143
Merge: 506b929 a60a684
Author: super <super@gmail.com>
Date:   Tue Jun 28 17:11:54 2016 +0800

    Merge branch 'master' of ssh://60.251.61.76:9022/opt/git/project/prj_nvp

commit 506b929f3e7ff1cb6ee63d343bdb478141ca34e4
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 16:27:05 2016 +0800

    add user2_fix

commit a60a684add1a5aedf3a37946e27130b82a42d29d
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 16:19:25 2016 +0800

    update: nvp6124_list.c + ohh.txt

commit 5403ef8db220f97fced2f46100439ae003987548
Author: paddy <paddy.chen@talitor.com.tw>
Date:   Tue Jun 28 12:07:06 2016 +0800

    Uploading source code


$git push origin master           //復原成功,push至Remote端.



























接下來,繼續完成你的工作!

分支管理branch

創建分支:
$git branch issue23

$git checkout -b issue23
顯示分支:

$git branch

切換分支:

$git checkout master
$git checkout issue23

Merge 

將分支合併至master:




















將分支issue23,issue24合併!

$git checkout master
$git merge issue24        //這種合併將commit往前移稱為fast-forward.

















接下來要合併issue23:

$git checkout master
$git merge issue23
















<Note***>

檔案遇到衝突;先用git status觀察;然後vi file修正問題,然後git commit.(相當於手動Merge)


rebase (在push之前)

與merge採取不同方式;此法將分支變更到你要合在一起的分支.

$git checkout issue23

$git rebase master






















再來做一次fast-forward:
$git checkout master
$git merge issue23

去除不再使用的分支:
$git branch -d issue24
$git branch -d issue23



<Note ***>
千萬不要對已經Push的東西做Rebase!


<Command>
$git log --graph --all       //圖形


<Reference>
1.Git官網
2.Git教學









































2016年6月18日 星期六

Ubuntu Dektop GUI 開機 切換成 Console開機


Ubuntu 16.04 boot: Console Mode

步驟1: 備份開機設定檔
$ sudo cp /etc/default/grub /etc/default/grub.orig
步驟2: 編輯/etc/default/grub
$ sudo vi /etc/default/grub

步驟3: 將下列變成註解
#GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash”

步驟4: 將GRUB_CMDLINE_LINUX=""變成
GRUB_CMDLINE_LINUX="text"

步驟5: #GRUB_TERMINAL=console的註解拿掉
GRUB_TERMINAL=console

步驟6: 執行"
$ sudo update‐grub

步驟7: 執行:$ sudo systemctl set-default multi-user.target

重新開機後,就會以文字模式登入!

步驟8: 如果要改回GUI模式開機,執行:
$ sudo systemctl set-default graphical.target
以上!



2016年5月30日 星期一

User is not in the sudoers file. This incident will be reported.


問題:$sudo su 出現錯誤.
$ sudo su 

錯誤訊息:
frank is not in the sudoers file.  This incident will be reported.


解決:編輯 /etc/sudoers; 將下列敘述加入檔案中.
frank   ALL=(ALL:ALL) ALL



以上!

2016年4月1日 星期五

Linux Virtual Memory


Virtual Memory Address (VMA)


  • User process 在4GB virtual memory 分配如下:
               (1)  1GB Kernel Space, 3GB User Space
                 或
               (2)  2GB Kernel Space, 2GB User Space


  • System分配給每個user process都是連續的virtual memory space,但是實際上的記憶體使用則是透過MMU來存取physical memory space.

  • 查詢Process對應的VMA

         #cat /proc/<pid>/maps


[root@GM]# cat /proc/360/maps
start    end      perm offset   ma:mi inode      image  
00008000-0000a000 r-xp 00000000 1f:03 32         /mnt/mtd/myapp
00012000-00013000 rwxp 00002000 1f:03 32         /mnt/mtd/myapp
00013000-00018000 rwxp 00000000 00:00 0          [heap]
76e38000-76e44000 rwxs 011b0000 00:0d 625        /dev/log_vg
76e44000-76e47000 r-xp 00000000 1f:02 174        /lib/libdl-0.9.33.2.so
76e47000-76e4e000 ---p 00000000 00:00 0 
76e4e000-76e4f000 r-xp 00002000 1f:02 174        /lib/libdl-0.9.33.2.so
76e4f000-76e50000 rwxp 00003000 1f:02 174        /lib/libdl-0.9.33.2.so
76e50000-76eb5000 r-xp 00000000 1f:02 172        /lib/libuClibc-0.9.33.2.so
76eb5000-76ebc000 ---p 00000000 00:00 0 
76ebc000-76ebd000 r-xp 00064000 1f:02 172        /lib/libuClibc-0.9.33.2.so
76ebd000-76ebe000 rwxp 00065000 1f:02 172        /lib/libuClibc-0.9.33.2.so
76ebe000-76ec3000 rwxp 00000000 00:00 0 
76ec3000-76f14000 r-xp 00000000 1f:02 165        /lib/libgm.so
76f14000-76f1c000 ---p 00000000 00:00 0 
76f1c000-76f1d000 rwxp 00051000 1f:02 165        /lib/libgm.so
76f1d000-76f28000 rwxp 00000000 00:00 0 
76f28000-76f3a000 r-xp 00000000 1f:02 158        /lib/libpthread-0.9.33.2.so
76f3a000-76f41000 ---p 00000000 00:00 0 
76f41000-76f42000 r-xp 00011000 1f:02 158        /lib/libpthread-0.9.33.2.so
76f42000-76f43000 rwxp 00012000 1f:02 158        /lib/libpthread-0.9.33.2.so
76f43000-76f45000 rwxp 00000000 00:00 0 
76f45000-76f4b000 r-xp 00000000 1f:02 156        /lib/ld-uClibc-0.9.33.2.so
76f50000-76f52000 rwxp 00000000 00:00 0 
76f52000-76f53000 r-xp 00005000 1f:02 156        /lib/ld-uClibc-0.9.33.2.so
76f53000-76f54000 rwxp 00006000 1f:02 156        /lib/ld-uClibc-0.9.33.2.so
7e93a000-7e95b000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]


欄位:
          perm: permission 
        ma:mi: major:minor