bloggerads

2017年4月19日 星期三

C : 好用的parsing 數字字串函式 strtol

strol (Convert string to long integer)

須include stdlib.h, 他的原型是 

long int strtol (const char* str, char** endptr, int base);

return value 是 轉換後的十進位值

第一個引數 str 是待轉換的數字字串指標

第二個引數 endptr 則是提供回傳parsing整串字串中, 空白字元分隔的下一個數字字串位址。 如果不用回傳,則給 NULL 即可

第三個引數是說明以什麼格式來 parsing 這個數字字串,  如 2 進位就給 2, 16 進位就給 16, 0 就是 自動偵測數字字串的格式。 (ps.) 16 進位可接受開頭為0x, 亦可接受大小寫

2017年4月16日 星期日

NVMe : Command flow

以下是發送一個NVMe admin/Io command 的流程。相關driver source code 可參考NVMe official website

1. Host Adds a command in the submission queue's tail entry

2. Host rings the submission queue's Tail Doorbell
3. Device fetch the command
4. Device process the command (done)
5. Device adds the completion result in the completion queue's tail entry (Completion result has its relevant command id)
6. Device send a Interrupt(Probably MSI-X)
7. Host reads the completion queue
  7.1 Host has received the completion command 
8. Host rings the completion queue's Head Doorbell


NVMe : Queue Size / Queue entry Size

Queue 相關 size 的 configuration

  • Admin Queue
  1. Completion Queue 和 Submission Queue 各只有一組
  2. Initial 時需設定Queue Size, 即AQA.ACQS, AQA.ASQS, controller 應support 2~4096個entry
  •  I/O Queue 
  1. Initial 時需設定每個entry的Size, 即 CC.IOSQES = 6 (64 Byte), CC.IOCQES = 4 (16 Byte), 這是NVM command的size。
  2. 透過 CAP.MQES (Maximum Queue Entries Supported)得到 I/O Submission/Completion Queue support 的最大entry數量(最少兩個entry)。 在使用Admin Command Create I/O Queue時不要超過他
  3. 透過 Set Feature (Feature Id 07h) 設定host driver所需的Submission/Completion Queues數量 (最大64K個), 從completion queue 回來的資料可以得到Controller 所能allocate 的Submission/Completion Queue數量

2017年4月8日 星期六

利用C語言的正規表達功能來Parsing 傳入程式中的引數

這篇介紹 C 的 sscanf 函數來做到類似 C++11 正規表達的效果,並以 Parsing 傳入程式中的引數做範例
// c.cpp

int main(int argc, char* argv[])
{
    char s0[30], s1[30];
    int ret;
    for (int i=argc-1; i>0; i--) {
        s0[0] = s1[0] = 0;
        //sscanf(argv[i], "%*[^:]:%s", s0); //[^:]代表在':'處設斷點但不包含':', '*'代表忽略'%'起始的字串
        sscanf(argv[i], "-%29[^:]:%29s", s0, s1); 
        if (s0[0] == 0 || s1[0] == 0) 
            puts("Wrong type!");
        else            
            printf("%s : %s\n", s0, s1);
    }   
  return 0;
}

----------------------Output---------------------------
> g++ -o c c.cpp
> c -name:John -age:20
age : 20
name : John

2017年2月5日 星期日

DOS : Legacy Graphic Output Control

在Dos下想輸出文字到螢幕上,除了呼叫C/C++提供的函數 printf, cout 或 Bios提供的軟體中斷 int 10, 是否有直接控制硬體的方法呢?  答案是有的,可以直接把要顯示的資料搬到A/B Segment。用以下的code來做範例 (Compile using Watcom)

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;

 enum Colour{ BLACK=0, BLUE, GREEN, CYAN, RED, MAGNETA, BROWN, LGRAY, \
   DGRAY=8, LBLUE, LGREEN, LCYAN, LRED, LMAGNETA, YELLOW, WHITE};
 
#define COLOUR(forecolour, backcolour)  ((backcolour) << 4 | (forecolour) & 0x0F)

 void WriteString(int y, int x, BYTE colour, char *string)
 {
     volatile WORD *pvram;
     
     for (DWORD i=0;string[i]!=0; x++, i++) {
       pvram = (volatile WORD *)0xB8000 + y * 80 + x;
       *pvram = (BYTE)string[i] | colour << 8;
     }
 }
 

 void WriteCharacter(int y, int x, BYTE colour, BYTE ch)
 {
      volatile WORD * pvram;
      pvram = (volatile WORD *)0xB8000 + (y * 80 + x) ;
      *pvram = ch | (colour << 8);
 }

 int main()
{
     WriteCharacter(1,0, COLOUR(RED, BLACK), 'H');    
     WriteCharacter(1,1, COLOUR(RED, BLACK), 'i');
     WriteString(1, 3, COLOUR(GREEN, BLACK), "Martin.");
}

在螢幕座標(y,x) = (1, 0) 秀出 Hi Martin.


ps. 如果想畫一個點陣圖請參考 mode 13h, 解析度為320*200, 256色, 透過寫入A000:0來完成


題外話, 我用了以上的技巧寫了一個Dos版的source code Editor, 名稱叫E editor (下圖)。 平常工作時都會開個Dos模擬器跑Dos tool,享受Dos單純的美。



Key:
F1: Copy Line
F2: Paste Line
F3: Delete Line
F10: Save File

下載: (password: martinlee)

E Editor

2017年1月13日 星期五

DOS : Increase Dosbox screen size in Windows

Step 1. Find dosbox-0.74.conf

Step 2. Modify the SDL part in the dosbox-0.74.conf


[SDL]

fullscreen=false 
fulldouble=false 
fullresolution=original 
windowresolution=1024x768 
output=ddraw 
autolock=true 
sensitivity=100 
waitonerror=true 
priority=higher,normal 
mapperfile=mapper.txt 
usescancodes=true 

ps. Some Dos application may consume lot of CPU usage. Fix it by Setting a fixed CPU cycles, for example, 16000.
[CPU]
cycles=auto 
cycles=16000

2016年12月2日 星期五

gcc : Built-in functions for atomic memory access

這一篇是研究Memory barrier的心得。研究的原因是因為在UEFI環境下使用multi-processor protocol 來驗證CPU design,過程用到了相關的gcc Atomic函式。Atomic 提供同步機制,使得在Multi-Processor/Multi-Thread的系統下操作同一塊memory, 各個Core的Cache都能確保和Memory同步。

這邊只是以軟體thread寫個應用程式作範例來解釋Memory barrier, 如果不使用Built-in functions for atomic memory access而將__sync_fetch_and_add(&count,1);改成count++, 則count結果會不正確。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

static int count = 0;

void *MyTest(void *arg)
{
        for (int i=0; i<20000; ++i)         
            __sync_fetch_and_add(&count, 1);
        return NULL;
}

int main(int argc, const char *argv[])
{
        pthread_t Thread_Id[10];
        int i;

        for (i=0;i<10;++i)
                pthread_create(&Thread_Id[i], NULL, MyTest, NULL);
       
                // Wait until all threads have finished.
        for (i=0;i<10;++i)
                pthread_join(Thread_Id[i], NULL);
       
        printf("%d\n",count);
        return 0;
}


另外,__sync_synchronize (): This built-in function issues a full memory barrier.呼叫這個函式讓每個Core上的cache和memory同步。

<note> UEFI kernel提供EFI_MP_SERVICES_PROTOCOL,透過這個protocol,可以指定呼叫某個/或多個CORE (AP)分別執行特定的function,達到Multi-processing的效果。

-------------------------------------------------------------------------------------------------------------------------
Ps. windows下測試,需要自行加入pthread這個library
如果你用Dev-C++ 5.11, Project->Parameters->Add library or object 加入
"../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libpthread.a"



順便解釋一下我認知的procces/thread:

process: 在系統中被註冊要執行的程式,其擁有CPU的使用權和獨立的位址空間。
thread: 系統處理工作的基本單位,一個CPU核心在同一時間只能提供一個thread來執行process
Multi-Thread: 將多個thread同時assign給一個process
Multi-Process: 每個process都分到thread來處理