|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| 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

|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
}

|Design| C++ getInstance

如果你要獲取特定的物件

就可以使用 getInstance()

這樣比全域變數看起來舒心一點

e.g. ————————————————————————

// test.h
class SomeService
{
public:
static SomeService &GetInstance();

}

// test.cpp
SomeService& SomeService::GetInstance()
{
static SomeService instance;
return instance;
}

————————————————————————


Ref. https://blog.csdn.net/fanyunda1988/article/details/51516930

|RIL| 建了 data 之後 ……

有了 APN,Modem 建了 data 之後會發生什麼事呢?

會長出網卡 ~~
可以使用 ifconfig 查看

別忘了設定 default route
route add default gw {IP-ADDRESS} {INTERFACE-NAME}

以及 DNS,才能用網域找到 ip
sudo echo nameserver 8.8.8.8 > /etc/resolv.conf

|Jobs| 系統廠工程師需要具備的 Linux 相關知識

  • IPC 溝通有許多方式(兩個 process 互相交換資料的方法)
  • 何時要開 proccess,何時用 multi-thread 就好
  • In C language, system()
  • Makefile 如何寫
  • 系統默認路徑
    • Include 系統默認搜尋範圍: /usr/include/usr/local/include
    • Lib 預設目錄: /lib、/usr/lib、/usr/local/lib
      • 環境變數 LD_LIBRARY_PATH 中指向搜索路徑
      • /etc/ld.so.conf 文件中增加搜索目錄
    • 執行檔預設目錄: 如果不加 ./ ,預設是執行 /bin、/usr/bin

|Code| 如何在 C++ 程式使用 C api ?

C++ 可以引用其他 C語言寫的 api,這不意外。

但要怎麼做?

C++:

請在把要使用的 C api 的 header 用 extern “C” 包起來

extern "C"
{
#include "demo_c_api_A.h"
#include "demo_c_api_B.h"
}

 

而要被使用的 C api 的 header:

demo_c_api_A.h:

#ifndef DEMO_C_API_A_H
#define DEMO_C_API_A_H

#include "aaa.h"
#include <bbb.h>

#ifdef __cplusplus
extern "C"
{
#endif

...

(C 的 header 原本該寫的東西)

...

#ifdef __cplusplus
}
#endif

#endif

 

你也可以不要直接用 extern 標全部,單獨寫:

#ifndef DEMO_C_API_A_H
#define DEMO_C_API_A_H

#include "aaa.h"
#include <bbb.h>

extern int c_api_A_init();


(C 的 header 原本該寫的東西)

#endif
#endif

 

 

延伸:extern 是什麼?

ref. Why use #ifndef CLASS_H and #define CLASS_H in .h file but not in .cpp?

WordPress.com.

Up ↑