|Design| Communicate with Kernel driver

User space can not exchange data with kernel space directly.
They need to use system call.
e.g. fopen, ioctl, write, read …… etc.

In Kernel Space ……
1. Register your device with “register_chrdev”, defined in linux/fs.h .
 https://ithelp.ithome.com.tw/articles/10159749
2. Implement driver functions, ioctl, open,…
 struct file_operations fops = {
  .owner = THIS_MODULE,
  .read = device1_read,
  .write = device1_write,
  .ioctl = device1_ioctl,
  .open = device1_open,
  .release = device1_release,
 };

 int ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 is in linux/ioctl.h
 http://ccckmit.wikidot.com/lk:io
 開發 driver 需要的基礎知識
 user space/kernel space 的IO觀念及實作

Copy data ……
 Kernel Space to User Space: copy_to_user()
 User Space to Kernel Space: copy_from_user()

In User Space ……
Use system call to control kernel driver.
 fopen (open)
 write
 read
 close
 seek
 poll / select
 ioctl
 mmap
 fcntl


e.g.

int main(int argc, char *argv[]){
  int devfd;
  int num = 0;

  if (argc > 1) num = atoi(argv[1]);
  if (num < 0) num = 0xff;

  devfd = open("/dev/debug", O_RDONLY);
  if (devfd == -1) {
    printf("Can't open /dev/debug\n");
    return -1;
  }

  printf("Write 0x%02x...\n", num);
  ioctl(devfd, IOCTL_WRITE, num);
  printf("Done. Wait 5 seconds...\n");
  sleep(5);
  close(devfd);

  return 0;
}

|Code| IPC methods

Originally, I though it is a basic interview question and everyone has at least a common answer .
Until I found someone did not know , I know I was wrong.

Threads can shares the same resources such as address space, file descriptors, stack and other process related attributes in the same process.
Processes can not share resources directly.

Processes will communicate to each other by IPC method.
There are two ways:
 1. Shared Memory
 2. Message passing

The following methods, which we often see, belong to message passing.
Pipe
Socket
Remote Procedural calls (RPCs)



https://www.geeksforgeeks.org/inter-process-communication-ipc/
https://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread

|Code| Makefile -I -L -l

e.g.
gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld


Means:
-I /home/hello/include
Find headers in sequence of /home/hello/include–>/usr/include–>/usr/local/include

-L /home/hello/lib:
Find librarys in sequence of /home/hello/lib–>/lib–>/usr/lib–>/usr/local/lib

-lworld:
Find the library “libworld.so” in the path of “-L /home/hello/lib “

|Code| How to use control flow by pthread_cond_timedwait()

There are three parameters related with pthread_cond_timedwait().

Definition:
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);

Parameters:
pthread_cond_t *restrict cond : the condition you want to trigger this flow
pthread_mutex_t *restrict mutex : Mutual exclusion
const struct timespec *restrict abstime : absolutely waiting time ( = system time + waiting



【Step by Step】

Initial the mutex:
1. pthread_mutex_init(pthread_mutex_t *restrict  __mutex ,
              const pthread_mutexattr_t *restrict __mutex_attr);
   __mutex_attr can be NULL.
   __mutex_attr is the parameter about mutex.
  If it is not NULL, go to “2.”

2. pthread_mutexattr_init(pthread_mutexattr_t * __mutex_attr );
 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
   type: PTHREAD_MUTEX_RECURSIVE,
      PTHREAD_MUTEX_NORMAL ……
3. pthread_cond_init(pthread_cond_t *restrict __cond ,
const pthread_condattr_t *restrict __cond_attr);

Start to wait for signal ” __cond “:
1. lock mutex: pthread_mutex_lock(&__mutex)
2. pthread_cond_timedwait(&__cond, &__mutex, &__abstime)
3. unlock mutex: pthread_mutex_unlock(&__mutex)

Start to send the signal ” __cond “:
1. lock mutex: pthread_mutex_lock(&__mutex)
2. pthread_cond_signal (&__cond)
3. unlock mutex: pthread_mutex_unlock(&__mutex)

Destroy the mutex:
1. pthread_mutex_destroy( pthread_mutex_t *restrict  __mutex );
2. pthread_mutexattr_destroy( pthread_mutexattr_t * __mutex_attr );
3. pthread_cond_destroy( pthread_cond_t *restrict __cond );

E.g.

// This thread will wait the signal.
void thread1(void *arg){
 int inArg = (int)arg;
 int ret = 0;
 struct timeval now;
 struct timespec outtime;

 pthread_mutex_lock(&g_mutex);

 gettimeofday(&now, NULL);
 outtime.tv_sec = now.tv_sec + 5;
 outtime.tv_nsec = now.tv_usec * 1000;
 ret = pthread_cond_timedwait(&g_cond, &g_mutex, &outtime);

 pthread_mutex_unlock(&g_mutex);
}


int main(void)
{
 pthread_t id1;
 int ret;

 // Initial mutex
 pthread_cond_init(&g_cond, NULL);
 pthread_mutex_init(&g_mutex, NULL);
 ret = pthread_create(&id1, NULL, (void *)thread1, (void *)1);

 if (0 != ret){
  printf(“thread 1 create failed!\n”);
  return 1;
 }

 printf(“Waiting %ds send the signal!\n”, SENDSIGTIME);
 sleep(SENDSIGTIME);

 // send the signal
 pthread_mutex_lock(&g_mutex);
 pthread_cond_signal(&g_cond);
 pthread_mutex_unlock(&g_mutex);
 pthread_join(id1, NULL);

 //Destroy the mutex
 pthread_cond_destroy(&g_cond);
 pthread_mutex_destroy(&g_mutex);
 return 0;
}

References:
https://blog.csdn.net/dead_g/article/details/73338960
https://linux.die.net/man/3/pthread_cond_timedwait
https://linux.die.net/man/3/pthread_cond_init
https://blog.csdn.net/yasi_xi/article/details/19112077

|Tools| Git v.s Repo

一般跟別人合作開發都是使用 git。那 repo 是什麼?
repo 是 Google 開發出來的工具,用來管理 Android 的。

一份 Android code 是由許多 project 組成的,每個 project 就是一個 git project。
repo 這個工具,就是可以管理 branches 以及眾多的 git project!

> repo init 後,可以找到 .repo/manifest.xml 這會記錄你控制的 projects

*基本工作流程與對照:

repo git
repo init -u URL -m ooxx.xml -b remote_branch git clone URL
repo sync -c git pull URL remote_branch:local_branch
repo start branch_name –all git branch branch_name
git status git status
git add git add
git commit git commit
repo upload . git push


*git 好用指令:
 > 查詢遠端的server 位置及名字
 git remote -v
 > 新增一個遠短 server
 git remote add {given_name} URL
 > 強迫 reset
 git reset –hard {local_branch}
 > 把 commit 推到遠端 branch
 git push {given_name} {local_branch}: refs/for/{remote_branch}
 > 從遠端 branch 拉 code 下來
 git pull {given_name} {remote_branch}:{local_branch}
 > 當前一個修改已 commit,又想把這次修改跟上一個修改一起 commit
 git commit –amend
 > 想上 patch 到某個已經 push 出去的 change
 git push {given_name} {local_branch}:refs/changes/{change_id}
 > 查詢某行的歷史
 git blame -L [行數] [檔案名]
 > 檢別 branch 的 commit 到目前的 branch
 git cherry-pick [sha-1]

*好用的配置
 > git commit 的模板:
 新增一個  ~/.git-template
 然後 git config commit.template ~/.git-template

 > 設置reviewers, git push rest,就會自動帶上 reviewers
 到 .git/config 編輯
 [remote “test”]
 pushurl = ssh://account@server_address:port/project_name
 push = {local_branch}:refs/for/{remote_branch}%r=someone1@mail, r=someone2@mail

*製作 patch,打 patch
 (在 branch A)
 git log
 git format-patch -1 [sha-1]
 mv ooxx.patch ~/
 (換到 branch B)
 git am [~/ooxx.patch]


值得注意的是:
pull 的 server / review 的 server / push 的 server 可能不同,
設置 push 的 server 時,請去確認 repo upload 時,到底是推到哪?


ref. [Coding] repo & git 的使用方法

|Design| bit map

如果你的某個宣告有多重意義,
但你一次只想知道某的欄位的狀態,可以善加利用 bit map

舉例:

#define status1 (uint_8) 1<<0
#define status2 (uint_8) 1<<1
#define status3 (uint_8) 1<<2

uint_8 test_case = 2;
int test_hex_case = 0xFA;

If( test_case & status1 ){ // false; 00000000 <- 00000010 & 00000001
  //do nothing
}
If( test_case & status2 ){ // true, not zero; 00000010 <- 00000010 & 00000010
  //do something
}
If( test_hex_case & status2 ){ // true, not zero;
// 0xFA = 1111 1010
// 00000010 <- 1111 1010 & 00000010
  // do something
}

|Jobs| 面試時的 Check Points

設定:
軟體工程師,非管理職
製造業/電子業
系統廠/ IC設計通用


(關於出差)
是否出差到工廠
出差頻率如何
出差地點是否為亞洲
出差膳雜費是實報實銷還是算天數
 ==>
 通常亞洲/工廠,如果頻率很常,要小心啦!
 基本上,實報實銷的一定是小氣公司

(關於加班)
平均部門下班時間
是否有加班費
 ==>
 請算好你的時薪 = 月薪/8/30
 如果沒有加班費,算法就是 = 月薪/常態上班時數/30
 每加薪 3000,相當於你時薪增加 12.5元
 我自己算法:每需要常太多工作一小時,月薪要增加至少 10000元 (沒加班費的公司)

(關於客戶)
是否有AE
是否有 issue tracker 系統


(關於debug)
是否有公版或模擬器
是否有自己的 log tool

(關於維護期)
案期多長, support期多
 ==>
 當你曾經接過 10年前的臭蟲,你就明白為何要問這個

WordPress.com.

Up ↑