|Linux| what is the difference between subsys_initcall and module_init ?

1. > If you trace two macro, both macro will be replace by __define_initcall(fn, *).
Hence, we can know that subsys_initcall will run earlier than module_init after INIT deamon stars ( do_initcalls ).

2. >
subsys_initcall() can only be used by a built-in (statically linked) module.
module_init can be used by either built-in or loadable modules.
For loadable *.ko modules, subsys_initcall() is mapped to the same as module_init() i.e. device_initcall()
ONLY one module_init() per driver module.

Reference,
root/include/linux/init.h
https://www.cnblogs.com/dakewei/p/10995453.html

|Design| Benefits of using Macro

What is the Macro?
If you write as “#define” in your code, that is “Macro” .

Macro will handle by the preprocessor.
You can think Macro as a method to replace the String which appears in you code..

pros:
– run faster than writing as function

cons:
– occupy memories

concepts:
– there is no the concept of pointer in macro.
just “replacing the string”

An question:
What is the output of the following code?

#define macro_to_func(pp) ({printf("in Macro ...\n"); minus ;})

void do_something(int *a, int *b){
    printf("do_something\n");
    int c;
    c = *a + *b;
    printf("do_something %d \n", c);
}

int minus(int *a, int *b){
    printf("minus\n");
    int c;
    c = *a - *b +1;
    printf("minus a = %d \n", *a);
    printf("minus b = %d \n", *b);
    printf("minus %d \n", c);
    return c;
}

int main()
{
    int (*do_something)(int* c, int* d);
    //printf("fptr 1 do_something %p\n", &do_something);

    int m = -1;
    int n = 7;

    printf("do_something = macro_to_func\n");
    do_something = macro_to_func(pp);
    //printf("fptr minus %p\n", &minus);
    //printf("fptr 2 do_something %p\n", &do_something);
    if(do_something){
        printf("in IF!!\n");
        do_something(&m, &n); --------------------------->???
    }
    return 0;
}

Answer:

do_something = macro_to_func
in Macro …
in IF!!
minus
minus a = -1
minus b = 7
minus -7

Explanation:
“int (*do_something)” is a local function pointer.
In the macro, the macro_to_func will be replaced as “minus”, but do_something !!!

|Code| LLVM initial

One day, if you want to implement a module on the platform x86_64 for arm64, you will need to know the tool chain, “cross compiler”.
The famous modern compiler is LLVM.

Why should we understand the compiler?
– build for multi-platform
– improve the efficiency of your code
– …..

I have a conclusion for the developer whose library is under the user space.
Use suitable optimization provided by LLVM, and make your code readable.
Dazzle coding is meaningless.

你所不知道的 C 語言:編譯器和最佳化原理篇
[共筆] 不深不淺,帶你認識 LLVM
“編譯器 LLVM 淺淺玩” by Pokai Chang

|Jobs| ARM symposium 2019

This event intruduce three fields.
Kigen OS for Sim
Mbed OS for IoT device
Pelion for IoT devices management

For our OEM, I think we need to improve the knowledge of OS, compile tool chain, and debug tools.

We can start from the usage of objdump.

GDB and Objdump

|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| Processes communicate by IPC methods

Threads can shares the same resources such as address space, file descriptors, stack and other process related attributes in the same process.
BUT 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: Socket, FIFO, POSIX message, dbus

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


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.



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

WordPress.com.

Up ↑