2020/11/6

pthread return value

pthread 可以 return value 給 parent process (who create it)
這個 方法:
#include <pthread.>
#include <stdio.h>
void *myThread()
{
   printf("in thread now\n");
   return (void *) 42;
}

int main()
{
   pthread_t tid;
   int status;

   pthread_create(&tid, NULL, myThread, NULL);
   pthread_join(tid, (void*)&status);

   printf("%d\n",status);   

   return 0;
}  
 
.. 這個 status 的宣告...
要測試 一下..

等等... 感覺怪怪的...
因為 return 一個 cast 成 (void*) 的 scalar value
...
要是看這一篇的話,thread要為return value alloc一塊記憶體,不能隨thread 退出兒消失。
經由把指標return 給 creator 後,creator 負責 free 掉。


有關 return 跟 exit() :
這一篇說明看起來好可怕...
對C++來說,return 會 call 所有 local scope 物件的 destructor,一一release 完再結束,而exit( )不會這樣做,它直接結束。
-- 可以寫sample code 試試,看看 1.不寫 2.return 3.exit( ) 對於 local 物件有蛇麼差別。


實際上用 g++ -S main.cpp 產生 assembly file 來看有 return 跟沒 return 的差別。
只插在 有return 的,多一個 intruction 把 return value 放到 eax,沒return 的,就放一個 nop (為什麼要放?)

add read/write function in i2c_client driver function

snd_soc_codec_driver
裡面有:
  • write : i2c_write
  • read : i2c_read
如果沒有指定,就會用 platform 內的。

所以如果想要 debug snd_soc_code driver,知道該 driver 對 i2c 的動作。
可以自己寫 i2c_read, i2c_write 放進去。
static unsigned int my_i2c_read(struct snd_soc_codec *codec, unsigned int reg)
{
    struct my_priv *mypriv = snd_soc_codec_get_drvdata(codec);
    int ret = -1; 
    unsigned char tx[1], rx[1];

    struct i2c_msg xfer[2];
    struct i2c_client *client = mypriv->i2c;

    tx[0] = reg;
    rx[0] = 0;

    /* Write register */
    xfer[0].addr = client->addr;
    xfer[0].flags = 0;
    xfer[0].len = 1;
    xfer[0].buf = tx;

    /* Read data */
    xfer[1].addr = client->addr;
    xfer[1].flags = I2C_M_RD;
    xfer[1].len = 1;
    xfer[1].buf = rx;

    ret = i2c_transfer(client->adapter, xfer, 2);

    if (ret != 2)
        printk("\t%s error ret = %d\n", __func__, ret);

    return (unsigned int)rx[0];

}

static int my_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
                unsigned int value)
{
    struct my_priv *mypriv = snd_soc_codec_get_drvdata(codec);
    int ret = -1;
    unsigned char tx[2];
    size_t  len = 2;

    if(reg==1)
        value |= 0x02; // don't power off spk 

    tx[0] = reg;
    tx[1] = value;

    printk("\t %s: (addr,data)=(%x, %x)\n", __func__, reg, value);

    ret = i2c_master_send(mypriv->i2c, tx, len);

    if (ret != len)
        return -EIO;

    return 0;
}
但是要struct my_priv 要把 probe 時,register 的 i2c client 田進變數
struct my_priv {
    struct i2c_client *i2c;
     ...
然後 module probe function...
static int my_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
    struct my_priv *mypriv;
    mypriv = devm_kzalloc(&i2c->dev. sizeof(struct my_priv), GFP_KERNEL);
    
    i2c_set_client_data(i2c, mypriv);
    mypriv->i2c = i2c;
    ...
這樣,這個 driver call snd_soc_read/write 時,就會 call 到 自己的 i2c_read/write function.
然後舊可以加 debug message...
但是這樣舊沒用到 regmap,所以 sys/kernel/debug/regmap/XXXX/registers 的內容不會顯示。

2020/11/5

nginx : get auth failcount behind proxy

proxy 後方的 restful server 要知道nginx 端 login fail 的次數。
可能要參考這一篇。
改用 auth_request module.
然後把 fail 頁面倒到令一個 restful api 上,並且把 failcount 放進 parameters..

.. 還沒試過..

使用 auth_request 的方法。可以參考這一篇

或是用 basic_auth,然後在 error page 時,導到 resetful server. 大概是這樣做

2020/11/3

記 一下 i2c tool 的動作, i2cget , i2cset

其實單獨執行。不加 argument 的時候,都會有 help.

# i2cdetect 
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cdetect -l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]

Detect I2C chips

	-l	List installed buses
	-F BUS#	List functionalities on this bus
	-y	Disable interactive mode
	-a	Force scanning of non-regular addresses
	-q	Use smbus quick write commands for probing (default)
	-r	Use smbus read byte commands for probing
	FIRST and LAST limit probing range


# i2cdetect -y -a 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- UU -- -- -- -- -- UU -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 


# i2cdump 
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cdump [-fy] [-r FIRST-LAST] BUS ADDR [MODE]

Examine I2C registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	b	Byte (default)
	w	Word
	W	Word on even register addresses
	i	I2C block
	s	SMBus block
	c	Consecutive byte
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode
	-r	Limit the number of registers being accessed


# i2cdump -fy 2 0x12
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: c9 06 48 01 60 50 0b 23 00 00 60 00 e1 e1 f0 00    ??H?`P?#..`.???.
10: 18 1e fc fc fc fc 07 03 03 d0 1f 60 20 00 10 00    ???????????` .?.
20: 00 0f 33 05 10 29 22 f6 bd 00 73 3e 79 e1 1d 03    .?3??)"??.s>y???
30: 92 39 3a e6 00 10 f1 1d 00 00 00 00 00 00 00 00    ?9:?.???........
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................


# i2cget
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cget [-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]

Read from I2C/SMBus chip registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	b	Read byte data (default)
	w	Read word data
	c	Write byte/read byte
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode


# i2cget -fy 2 0x12 0
0xc9
# i2cget -fy 2 0x12 1
0x06


# i2cset
BusyBox v1.31.1 (2020-02-18 12:01:00 CST) multi-call binary.

Usage: i2cset [-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]

Set I2C registers

	I2CBUS	I2C bus number
	ADDRESS	0x03-0x77
MODE is:
	c	Byte, no value
	b	Byte data (default)
	w	Word data
	i	I2C block data
	s	SMBus block data
	Append p for SMBus PEC

	-f	Force access
	-y	Disable interactive mode
	-r	Read back and compare the result
	-m MASK	Mask specifying which bits to write
# i2cset -fy 2 0x12 0 0xc8
# i2cget -fy 2 0x12 0
0xc8

clang, disable optimize for latter pass

這一篇,用 llvm-11 的話,opt 的指令沒有效。
stack overflow 有說。
在 compile 時,如果沒有加上 -O,在產生的 ll file, function 錢會有 optnone,避免 reg2mem 做 optimization:
; Function Attrs: noinline nounwind optnone uwtable
define i32 @add(i32, i32) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
所以 compile 時要加場上 -O
clang -S -emit-llvm -O  main.c
這樣就不會有 optnone 的標記:
; Function Attrs: norecurse nounwind readnone uwtable
define i32 @add(i32, i32) local_unnamed_addr #0 {
  %3 = add nsw i32 %1, %0
  ret i32 %3
}
但是也optimize 過了...

如果不要他先 optimize,又要加
clang -S -emit-llvm -O -Xclang -disable-llvm-passes main.c
這樣才能完成跟街學文章一樣的code
; Function Attrs: nounwind uwtable
define i32 @add(i32, i32) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4, !tbaa !2
  store i32 %1, i32* %4, align 4, !tbaa !2
  %5 = load i32, i32* %3, align 4, !tbaa !2



最後,用 as 和 ld link 出 exeutable file,
要指定 crt1.o, crti.o,但是最終還是無法執行。

可能是 default library 的關係。
用 gcc assembly front-end 舊可以..
gcc main.s -no-pie -o main
用 -v 可以看一下 gcc ld 的 default crt.o 和 library
或許照著寫舊可以用 ld 成功 link..

這一篇 就是這樣做
ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 test.o  /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib64/gcc/x86_64-linux/4.3/crtbegin.o -lc /usr/lib64/gcc/x86_64-linux/4.3/crtend.o /usr/lib64/crtn.o
用了 ld-linux-x86-64.so crti.o crtbegin.o

依照 error mesaage,最後。minimum:
ld main.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o -lc
但是link 出來的 a.out 執行出現 'No such file or directory'

這一篇 的回答好像才是重點,interpreter 的問題。
用 gcc compile 的 a.out 和 ld link 出來的 a.out,用 readelf -l 看, interpreter 不一樣。

用 patchelf 的話..
$ patchelf --print-interpreter a.out 
/lib/ld64.so.1
$ patchelf --print-interpreter gmain 
/lib64/ld-linux-x86-64.so.2
不一樣。
實際上沒有 /lib/ld64.so.1
所以 Error message 是 'No sunch file or directory'

用 patchelf 設定正確的 interpreter;
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 a.out 
所以。最後,正確 ld 的 command 是:
ld -o a.out -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o -lc  /usr/lib/x86_64-linux-gnu/crtn.o main.

這一篇 有詳細講crtX.o 和 interpreter 之間的關係和實驗。

2020/11/2

https 基本原理

Browser, Server 都先準備好自己的 private/public key pair

  • Browser 透過 https 向 Server 發出 request
  • Server 把自己經過 CA 認證的 site.crt 送給 browser,(crt 裡面有 server 的 public key 和 CA 的 sign
  • Browser 收到 crt, 先用 CA 的 public key 確認 crt 裡,CA 的 sign 是正確的,還有 checksum 正確,代表 crt 沒被竄改
  • Browser 把 crt 裡的 public 拿出來,加密自己的 public key,送給 Server
  • Server 收到 Browser 的 public key 了
完成以上動作後,Browser, Server 就互相有對方的 public key 了。

兩人用對方的 public 加密送資料給對方。
對方就可以用自己的 private key 解開。

用 tls 通訊 Boost 的 example

boost asio 有 ssl 的 programming example: 但是沒有操作說明。

這一篇是 操作說明,可惜是以 windows 為 platform
.. 現在在 linux 上試試看。

這一篇 也有產生 key, crt 和example 修改的範例
這一篇用 boost asio ssl 模擬 browser 對 https 的 request 動作。



先亂寫一下...,不知道政不正確...

SSL certication
  • Cryptographic Key
  • server/domain , organization name
某網站的公鑰

然後這個 certication 是經果某個機構認證的。
機構:Cerfitication Authority (CA)

把自己的 public key 和自己的 location, domain name 包成 CSR (Certificate Signing Request) 格式,交給 CA
CA 會去檢查你是不是就是這個 CSR 內的 domain owner
-- 會要求你提供一堆資料。

CA 確認的話,CA 就會寄一份 SSL certification 給你,內容包含你的機構名稱,public key。
然後你就可以把這個SSL certication 放在你的 server 中。

CA 寄給你的 SSL certification 會包另一個 " trust root" 的 certification。

Browser 都會內建一堆 CA 機構的的 Root certification。
這樣舊知道你的 SSL certification 是不是真的。

browser 收到你用 private 加密的內容。
browser 有你的 SSL 憑證,包含一個CA root 的認證。好確保這個憑證是真的。
裡面有你的 public key,可以用來解開你用 private key 加密的內容。


CSR 送給 CA 機構,他確認正確後,就會把CSR 的資料斷做 checksum,然後用CA 自己的 private key 加密後,附在你的 CSR 後面。t
這就是CRT 了。
CA 會把 CRT 寄給你。


browser 都有內建一堆 CA 的 public key.
所以收到某網站的 CRT,他先用 CA 的 public key 確認這格 CRT 真的是 CA 認可(sign) 過得。
然後因為 checksum 的關係,。同時確認這格 CRT 沒有被修改。
這樣他就可以相信這個 CRT 裡的 public key 跟 domain 資料。
舊可以用 public key 來解開/確認這格 domain 用 private key 加密過後的資料。



openssl 可以作到所有的事,也可以用來列出 CSR, CRT, Key 的內容。

產生 private key
openssl genesa -out mypriv.key 4096
用private key 做出 CSR
openssl req -out mysite.csr -key mypriv.key -new



這一篇 使用 openssl 產生 private/public key pair。
然後各自加密檔案,再用對方解密。
同時還說明 crt 中用來 verify signature 的方法(command)


這一篇直接寫出command.
# Generate keys
openssl genrsa -out key.pem
openssl rsa -in key.pem -out key.pub -pubout

# Encrypt and Decrypt a file (using public key to encrypt)
echo --pass-- >> pass.txt
openssl rsautl -in pass.txt -out pass.enc -pubin -inkey key.pub -encrypt
openssl rsautl -in pass.enc -out pass.dec -inkey key.pem -decrypt
cat pass.dec