Android adb shell input 事件用法

本篇教學介紹如何在 Android 下使用 adb shell input 指令,adb shell input 最常用到 keyevent,可以很方便地模擬按鍵輸入,讓開發除錯或自動化測試上變得方便許多。

以下 adb shell input 內容大概分為這幾部分,

  • adb shell input keyevent 模擬按鍵
  • adb shell input keyevent 常用的 keycode 值
  • adb shell input keyevent 完整的 keycode 值
  • adb shell input text 模擬輸入文字
  • adb shell input tap 模擬觸控螢幕
  • adb shell input swipe 模擬滑動螢幕

adb 指令的安裝方式可以參考這篇
那我們開始吧!

adb shell input keyevent 模擬按鍵

如果要模擬 A 按鍵你可以下這 adb 指令, B 按鍵碼則是 30

1
2
3
adb shell input keyevent 29
或者
adb shell input keyevent KEYCODE_A

如果要模擬按下 HOME 你可以下這 adb 指令,

1
2
3
adb shell input keyevent 3
或者
adb shell input keyevent KEYCODE_HOME

如果要模擬按下音量鍵變大聲,你可以下這 adb 指令,

1
2
3
adb shell input keyevent 24
或者
adb shell input keyevent KEYCODE_VOLUME_UP

adb shell input keyevent 常用的 keycode 值

這邊整理 input keyevent 常用的 keycode 值,

1
2
3
4
5
6
7
8
9
10
3  -> // Home 回到主畫面
4 -> // Back 返回
19 -> // Up 上
20 -> // Down 下
21 -> // Left 左
22 -> // Right 右
23 -> // Select/Ok 確定選取
24 -> // Volume Up 音量上
25 -> // Volume Down 音量下
82 -> // Menu 選單

adb shell input keyevent 完整的 keycode 值

這邊列出所有的 keyevent 跟對應的 key code,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
0  -> "KEYCODE_UNKNOWN"
1 -> "KEYCODE_MENU"
2 -> "KEYCODE_SOFT_RIGHT"
3 -> "KEYCODE_HOME" // 回到主畫面
4 -> "KEYCODE_BACK" // 返回
5 -> "KEYCODE_CALL" // 打電話介面
6 -> "KEYCODE_ENDCALL" // 關閉螢幕
7 -> "KEYCODE_0"
8 -> "KEYCODE_1"
9 -> "KEYCODE_2"
10 -> "KEYCODE_3"
11 -> "KEYCODE_4"
12 -> "KEYCODE_5"
13 -> "KEYCODE_6"
14 -> "KEYCODE_7"
15 -> "KEYCODE_8"
16 -> "KEYCODE_9"
17 -> "KEYCODE_STAR"
18 -> "KEYCODE_POUND"
19 -> "KEYCODE_DPAD_UP" // 上
20 -> "KEYCODE_DPAD_DOWN" // 下
21 -> "KEYCODE_DPAD_LEFT" // 左
22 -> "KEYCODE_DPAD_RIGHT" // 右
23 -> "KEYCODE_DPAD_CENTER" // 確定選取
24 -> "KEYCODE_VOLUME_UP" // 音量上
25 -> "KEYCODE_VOLUME_DOWN" // 音量下
26 -> "KEYCODE_POWER" // 電源鍵
27 -> "KEYCODE_CAMERA" // 拍照鍵
28 -> "KEYCODE_CLEAR"
29 -> "KEYCODE_A"
30 -> "KEYCODE_B"
31 -> "KEYCODE_C"
32 -> "KEYCODE_D"
33 -> "KEYCODE_E"
34 -> "KEYCODE_F"
35 -> "KEYCODE_G"
36 -> "KEYCODE_H"
37 -> "KEYCODE_I"
38 -> "KEYCODE_J"
39 -> "KEYCODE_K"
40 -> "KEYCODE_L"
41 -> "KEYCODE_M"
42 -> "KEYCODE_N"
43 -> "KEYCODE_O"
44 -> "KEYCODE_P"
45 -> "KEYCODE_Q"
46 -> "KEYCODE_R"
47 -> "KEYCODE_S"
48 -> "KEYCODE_T"
49 -> "KEYCODE_U"
50 -> "KEYCODE_V"
51 -> "KEYCODE_W"
52 -> "KEYCODE_X"
53 -> "KEYCODE_Y"
54 -> "KEYCODE_Z"
55 -> "KEYCODE_COMMA"
56 -> "KEYCODE_PERIOD"
57 -> "KEYCODE_ALT_LEFT"
58 -> "KEYCODE_ALT_RIGHT"
59 -> "KEYCODE_SHIFT_LEFT"
60 -> "KEYCODE_SHIFT_RIGHT"
61 -> "KEYCODE_TAB"
62 -> "KEYCODE_SPACE"
63 -> "KEYCODE_SYM"
64 -> "KEYCODE_EXPLORER"
65 -> "KEYCODE_ENVELOPE"
66 -> "KEYCODE_ENTER"
67 -> "KEYCODE_DEL"
68 -> "KEYCODE_GRAVE"
69 -> "KEYCODE_MINUS"
70 -> "KEYCODE_EQUALS"
71 -> "KEYCODE_LEFT_BRACKET"
72 -> "KEYCODE_RIGHT_BRACKET"
73 -> "KEYCODE_BACKSLASH"
74 -> "KEYCODE_SEMICOLON"
75 -> "KEYCODE_APOSTROPHE"
76 -> "KEYCODE_SLASH"
77 -> "KEYCODE_AT"
78 -> "KEYCODE_NUM"
79 -> "KEYCODE_HEADSETHOOK"
80 -> "KEYCODE_FOCUS" // 拍照對焦鍵
81 -> "KEYCODE_PLUS"
82 -> "KEYCODE_MENU" // 解鎖滑屏/Menu 選單
83 -> "KEYCODE_NOTIFICATION" // 通知鍵
84 -> "KEYCODE_SEARCH" // 搜尋鍵
85 -> "KEYCODE_MEDIA_PLAY_PAUSE" 多媒體鍵 播放/暫停
86 -> "KEYCODE_MEDIA_STOP" // 多媒體鍵 停止
87 -> "KEYCODE_MEDIA_NEXT" // 多媒體鍵 下一首
88 -> "KEYCODE_MEDIA_PREVIOUS" // 多媒體鍵 上一首
89 -> "KEYCODE_MEDIA_REWIND" // 多媒體鍵 快退
90 -> "KEYCODE_MEDIA_FAST_FORWARD" // 多媒體鍵 快進
91 -> "KEYCODE_MUTE" // 靜音
92 -> "KEYCODE_PAGE_UP"
93 -> "KEYCODE_PAGE_DOWN"
94 -> "KEYCODE_PICTSYMBOLS"
...
122 -> "KEYCODE_MOVE_HOME"
123 -> "KEYCODE_MOVE_END"
126 -> "KEYCODE_MEDIA_PLAY" // 多媒體鍵 播放
127 -> "KEYCODE_MEDIA_PAUSE" // 多媒體鍵 暫停
...
187 -> "KEYCODE_APP_SWITCH" // 所有任務視窗

更完整的列表可以查詢 android 開發者網站的 KeyEvent

adb shell input text 模擬輸入文字

這邊介紹 adb shell input text 模擬輸入文字,如果要模擬輸入 android 字串的話,可以下這 adb 指令,

1
adb shell input text "android"

adb shell input tap 模擬觸控螢幕

這邊介紹 adb shell input tap 模擬觸控螢幕,例如模擬觸控點擊(600,800)位置,其中X座標是600,Y座標是800,

1
adb shell input tap 600 800

adb shell input swipe 模擬滑動螢幕

這邊介紹 adb shell input swipe 模擬滑動螢幕,例如模擬在螢幕上從(600,800)向左滑動到(300,800),就會看到畫面右滑動,

1
adb shell input swipe 600 800 300 800

完整的用法為 input swipe <x1> <y1> <x2> <y2> [duration(ms)]
要模擬長按的話,在最後多加一個參數,例如 250 表示長按 250 ms。

其他參考
android - ADB Shell Input Events - Stack Overflow
https://stackoverflow.com/questions/7789826/adb-shell-input-events
[android-developers] Re: correct usage of “adb shell input”
https://www.mail-archive.com/android-developers@googlegroups.com/msg14587.html
adb shell 命令整理 | IT人
https://iter01.com/476261.html
adb shell input keyevent 控制按鍵輸入的數值
https://www.796t.com/content/1549161557.html

其他技巧推薦

如果你是常常在Android adb shell下做事情的話,尤其是需要使用到vi,建議安裝busybox,使用busybox附帶的vi會方便很多,
如果還想知道busybox支援哪些指令或busybox基本用法的話請看這篇
其他的 Android 系列文章可以看這篇

Python pip install 如何安裝指定版本的套件

本篇紀錄 Python 如何使用 pip install 安裝指定版本的套件,pip 安裝套件的話預設它會幫你裝到最新版本,
如果使用 pip 安裝該套件最新的版本連帶很多相依套件都要裝到最新的話出了問題,
最後只想裝某個指定的版本怎麼辦?

pip install 指定版本用法如下:
pip install [套件名稱]==[版號]

例如:pip 安裝 opencv 套件的 3.4.9.33 的版本的話就是這樣使用,
pip install opencv-python==3.4.9.33

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包
Python 安裝 OpenCV 模組
macOS 使用 pip 安裝 opencv

C/C++ Linux pthread_detach 用法與範例

本篇 ShengYu 介紹 C/C++ Linux/Unix 執行緒 pthread_detach() 用法,pthread_detach() 是標示該執行緒為 detach 狀態。一個 detach 執行緒結束時,他的資源會自動釋放歸還給系統,而不需要另一個執行緒使用 join 的方式來結束該執行緒。

pthread_detach 基本用法

以下簡單示範如何使用 pthread_detach(),當一個執行緒變成 detach 狀態時,它就不能使用 pthread_join() 來 join 或者變成 joinable。

在 main 主程式中用 pthread_create() 建立執行緒後使用 pthread_detach() 將該執行緒變成 detach 狀態,之後即使主程式要結束退出也會等待該執行緒結束才退出,範例如下,

cpp-pthread_detach.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// g++ cpp-pthread_detach.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");

return (void *)"hello";
}

int main() {
pthread_t t1;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
}

pthread_detach(t1);

printf("main end\n");

return 0;
}

結果輸出如下,

1
2
main end
foo

其它參考
pthread_detach(3) - Linux manual page
https://man7.org/linux/man-pages/man3/pthread_detach.3.html

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_join 用法與範例
C/C++ Linux pthread_exit 用法與範例
C/C++ Linux/Unix 讓執行緒跑在指定 CPU 的方法 sched_setaffinity
C/C++ Linux/Unix pthread 建立多執行緒用法與範例
C++ std::thread 建立多執行緒用法與範例

C/C++ Linux pthread_exit 用法與範例

本篇 ShengYu 介紹 C/C++ Linux/Unix 執行緒 pthread_exit() 用法,pthread_exit() 是用來結束該執行緒並透過 pthread_exit 的 retval 參數來回傳值,該回傳值可被 pthread_join 取得到。

pthread_exit 基本用法

以下簡單示範如何使用 pthread_exit(),在 foo 函式裡用 pthread_exit() 並回傳 123 數字,接著在 main 主程式中用 pthread_join() 接收到這個回傳值並且印出來,

cpp-pthread_exit.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// g++ cpp-pthread_exit.cpp -o a.out -pthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo 1\n");

int *result = (int *)malloc(sizeof(int));
*result = 123;
pthread_exit(result);
printf("foo 2\n");
return NULL;
}

int main() {
pthread_t t1;
int *retval;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

if (pthread_join(t1, (void **)&retval) != 0) {
fprintf(stderr, "Error: pthread_join\n");
return 1;
}

printf("retval: %d\n", *retval);
free(retval);
return 0;
}

結果輸出如下,

1
2
foo 1
retval: 123

這邊另外介紹在 foo 函式裡用 pthread_exit() 並回傳 hello 字串,接著在 main 主程式中用 pthread_join() 接收到這個回傳值並且印出來,

cpp-pthread_exit2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// g++ cpp-pthread_exit2.cpp -o a.out -pthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo 1\n");

char *result = (char *)malloc(32 * sizeof(char));
strcpy(result, "hello");
pthread_exit(result);
printf("foo 2\n");
return NULL;
}

int main() {
pthread_t t1;
char *retval;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

if (pthread_join(t1, (void **)&retval) != 0) {
fprintf(stderr, "Error: pthread_join\n");
return 1;
}

printf("retval: %s\n", retval);
free(retval);
return 0;
}

結果輸出如下,

1
2
foo 1
retval: hello

pthread_exit 其它使用情境

這邊介紹 pthread_exit 另一個使用情境,有時 main 主程式已經執行完畢並結束,那麼建立出來的執行緒就終止了,如下範例,

cpp-pthread_exit3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// g++ cpp-pthread_exit3.cpp -o a.out -pthread
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo ++\n");
sleep(3);
printf("foo --\n");
return NULL;
}

int main() {
printf("main ++\n");
pthread_t t1;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

sleep(1);
printf("main --\n");
return 0;
}

結果輸出如下,

1
2
3
main ++
foo ++
main --

如果要讓建立出來的執行緒不被 main 主程式的結束退出影響時,就需要在主程式結束時呼叫 pthread_exit(),這樣會等到所有執行緒結束後 main 才會退出,如下範例,

cpp-pthread_exit4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// g++ cpp-pthread_exit4.cpp -o a.out -pthread
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo ++\n");
sleep(3);
printf("foo --\n");
return NULL;
}

int main() {
printf("main ++\n");
pthread_t t1;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

printf("pthread_exit\n");
pthread_exit(NULL);
printf("main --\n");
return 0;
}

而使用 pthread_exit 自然不會執行到後面的 printf("main --\n");return 0,輸出結果如下,

1
2
3
4
main ++
pthread_exit
foo ++
foo --

以上就是 C/C++ Linux pthread_exit 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它參考
pthread_exit(3) - Linux manual page
https://man7.org/linux/man-pages/man3/pthread_exit.3.html
pthread_exit()函數:終止線程
http://c.biancheng.net/view/8608.html

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_join 用法與範例
C/C++ Linux pthread_detach 用法與範例
C/C++ Linux/Unix 讓執行緒跑在指定 CPU 的方法 sched_setaffinity
C/C++ Linux/Unix pthread 建立多執行緒用法與範例
C++ std::thread 建立多執行緒用法與範例

C/C++ Linux pthread_join 用法與範例

本篇 ShengYu 介紹 C/C++ Linux/Unix 執行緒 pthread_join() 用法,pthread_join() 是在當前執行緒等待指定的執行緒執行完畢。

pthread_join 基本用法

使用 pthread_join 會在當前執行緒阻塞並等待指定的執行緒執行完畢,如果指定的執行緒已經終止那麼 pthread_join 會立即回傳,指定的執行緒必須是 joinable 的。

pthread_join 對於 pthread 很重要,不呼叫 pthread_join 可能會造成建立的執行緒沒有執行完畢的問題,以下簡單示範如何使用 pthread_join()

cpp-pthread_join.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// g++ cpp-pthread_join.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");

return NULL;
}

int main() {
pthread_t t1;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

if (pthread_join(t1, NULL) != 0) {
fprintf(stderr, "Error: pthread_join\n");
return 1;
}

return 0;
}

pthread_join 取得回傳值

這邊示範用 pthread_join 來取得執行緒的回傳值,在 foo 回傳 123 整數,在 main 主程式裡用 pthread_join 等待執行緒執行結束並將 retval 印出來,

cpp-pthread_join2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// g++ cpp-pthread_join2.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");

return (void *)123;
}

int main() {
pthread_t t1;
void *retval;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

if (pthread_join(t1, &retval) != 0) {
fprintf(stderr, "Error: pthread_join\n");
return 1;
}

if (retval != NULL) {
printf("retval: %d\n", retval);
}

return 0;
}

輸出結果如下,

1
2
foo
retval: 123

這邊示範用 pthread_join 來取得執行緒的回傳值,在 foo 回傳 hello 字串,在 main 主程式裡用 pthread_join 等待執行緒執行結束並將 retval 印出來,

cpp-pthread_join3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// g++ cpp-pthread_join3.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");

return (void *)"hello";
}

int main() {
pthread_t t1;
void *retval;

if (pthread_create(&t1, NULL, foo, NULL) != 0) {
fprintf(stderr, "Error: pthread_create\n");
return 1;
}

if (pthread_join(t1, &retval) != 0) {
fprintf(stderr, "Error: pthread_join\n");
return 1;
}

if (retval != NULL) {
printf("retval: %s\n", (char *)retval);
}

return 0;
}

輸出結果如下,

1
2
foo
retval: hello

其它參考
pthread_join(3) - Linux manual page
https://man7.org/linux/man-pages/man3/pthread_join.3.html

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_detach 用法與範例
C/C++ Linux pthread_exit 用法與範例
C/C++ Linux/Unix 讓執行緒跑在指定 CPU 的方法 sched_setaffinity
C/C++ Linux/Unix pthread 建立多執行緒用法與範例
C++ std::thread 建立多執行緒用法與範例

C/C++ Linux pthread_attr_getstacksize 取得執行緒堆疊大小用法

本篇 ShengYu 介紹 C/C++ Linux/Unix 執行緒 pthread_attr_getstacksize() 用法,pthread_attr_getstacksize() 是用來取得該執行緒的堆疊大小。

pthread_attr_getstacksize 基本用法

pthread_create() 建立執行緒時沒有設定堆疊大小的話會採用系統的預設值,在 shell 下輸入 ulimit -s 就可以看到目前系統的設定值,單位為 KB,如下所示目前數值為 8192KB,也就是 8M,也可以透過 ulimit 來改變系統預設的 stack size 大小。

1
2
$ ulimit -s
8192

這邊介紹透過 pthread_attr_getstacksize 來取得執行緒的 stack 堆疊大小。
pthread 堆疊最小值定義為 PTHREAD_STACK_MIN,也就是 16384bytes。

以下簡單示範如何使用 pthread_attr_getstacksize()

cpp-pthread_attr_getstacksize.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// g++ cpp-pthread_attr_getstacksize.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

int main() {
pthread_attr_t attr;
int ret;
size_t stacksize;

ret = pthread_attr_init(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_init\n");
}

ret = pthread_attr_getstacksize(&attr, &stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_getstacksize\n");
}

printf("stack size: %lu\n", stacksize);

ret = pthread_attr_destroy(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_destroy\n");
}

return 0;
}

輸出如下,

1
stack size: 8388608

設定 stack size 後再取得 stack size

這邊示範先設定 stack size 後再試著取得 stack size 看看跟設定的是否一致,

cpp-pthread_attr_getstacksize2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// g++ cpp-pthread_attr_getstacksize2.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

int main() {
pthread_attr_t attr;
int ret;
size_t stacksize;

ret = pthread_attr_init(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_init\n");
}

ret = pthread_attr_getstacksize(&attr, &stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_getstacksize\n");
}
printf("stack size: %lu\n", stacksize);

ret = pthread_attr_setstacksize(&attr, 96*1024);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_setstacksize\n");
}

ret = pthread_attr_getstacksize(&attr, &stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_getstacksize\n");
}
printf("stack size: %lu\n", stacksize);

ret = pthread_attr_destroy(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_destroy\n");
}

return 0;
}

輸出如下,

1
2
stack size: 8388608
stack size: 98304

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_attr_setstacksize 設定執行緒堆疊大小用法
C/C++ Linux/Unix 讓執行緒跑在指定 CPU 的方法 sched_setaffinity
C/C++ Linux/Unix pthread 建立多執行緒用法與範例
C++ std::thread 建立多執行緒用法與範例

C/C++ Linux pthread_attr_setstacksize 設定執行緒堆疊大小用法

本篇 ShengYu 介紹 C/C++ Linux/Unix 執行緒 pthread_attr_setstacksize() 用法,pthread_attr_setstacksize() 是用來設定該執行緒的堆疊大小。

pthread_attr_setstacksize 基本用法

pthread_create() 建立執行緒時沒有設定堆疊大小的話會採用系統的預設值,在 shell 下輸入 ulimit -s 就可以看到目前系統的設定值,單位為 KB,如下所示目前數值為 8192KB,也就是 8M,也可以透過 ulimit 來改變系統預設的 stack size 大小。

1
2
$ ulimit -s
8192

這邊介紹不改動系統的預設值,而是透過 pthread_attr_setstacksize 來改變執行緒的 stack 堆疊大小。
pthread 堆疊最小值定義為 PTHREAD_STACK_MIN,也就是 16384bytes,pthread_attr_setstacksize() 設定小於 PTHREAD_STACK_MIN 的話會回傳 0 (表示設定失敗),

以下簡單示範如何使用 pthread_attr_setstacksize(),stack size 要在執行緒建立之前設定,也就是傳入 attr 給 pthread_create,執行緒建立後是無法再改動 stack size 的。

cpp-pthread_attr_setstacksize.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// g++ cpp-pthread_attr_setstacksize.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");
return NULL;
}

int main() {
pthread_t t1;
pthread_attr_t attr;
int ret;
size_t stacksize = 65536;

ret = pthread_attr_init(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_init\n");
}

ret = pthread_attr_setstacksize(&attr, stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_setstacksize\n");
}

ret = pthread_create(&t1, &attr, foo, NULL);
if (ret != 0) {
fprintf(stderr, "Error: pthread_create\n");
}

pthread_join(t1, NULL);

ret = pthread_attr_destroy(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_destroy\n");
}

return 0;
}

補充:若要使用 PTHREAD_STACK_MIN 定義的話,需 include <limits.h>

設定完後,可以使用 pthread_attr_getstacksize 來取得 stack size,如下面範例,

cpp-pthread_attr_setstacksize2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// g++ cpp-pthread_attr_setstacksize2.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void * foo(void *arg) {
printf("foo\n");
return NULL;
}

int main() {
pthread_t t1;
pthread_attr_t attr;
int ret;
size_t stacksize = 65536;

ret = pthread_attr_init(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_init\n");
}

ret = pthread_attr_setstacksize(&attr, stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_setstacksize\n");
}

size_t stacksize2;
ret = pthread_attr_getstacksize(&attr, &stacksize2);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_getstacksize\n");
}
printf("stack size: %zu\n", stacksize2);

ret = pthread_create(&t1, &attr, foo, NULL);
if (ret != 0) {
fprintf(stderr, "Error: pthread_create\n");
}

pthread_join(t1, NULL);

ret = pthread_attr_destroy(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_destroy\n");
}

return 0;
}

結果輸出如下,

1
2
stack size: 65536
foo

不過這樣算是從 attr 這變數裡取出 stack size,不算真正這個 thread 的 stack size,正確做法應該如下,

以下是在 foo 函數內取得該 thread 的 stack size,是透過 pthread_getattr_np 函式重新取得 attr 變數後再用 pthread_attr_getstacksize 取得 stack size。
請注意,pthread_getattr_np 函數並不是 POSIX 標準的一部分,但它在一些 POSIX 系統上是可用的。這個函式可以用來獲取執行緒的屬性,包括 stack 大小等資訊。以下是範例程式碼:

cpp-pthread_attr_setstacksize3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// g++ cpp-pthread_attr_setstacksize3.cpp -o a.out -pthread
#include <stdio.h>
#include <pthread.h>

void printStackSize() {
pthread_attr_t attr;
int ret;
size_t stacksize;

ret = pthread_getattr_np(pthread_self(), &attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_getattr_np\n");
}

ret = pthread_attr_getstacksize(&attr, &stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_getstacksize\n");
}

printf("stack size: %zu\n", stacksize);
}

void * foo(void *arg) {
printf("foo\n");
printStackSize();
return NULL;
}

int main() {
pthread_t t1;
pthread_attr_t attr;
int ret;
size_t stacksize = 65536;

ret = pthread_attr_init(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_init\n");
}

ret = pthread_attr_setstacksize(&attr, stacksize);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_setstacksize\n");
}

ret = pthread_create(&t1, &attr, foo, NULL);
if (ret != 0) {
fprintf(stderr, "Error: pthread_create\n");
}

pthread_join(t1, NULL);

ret = pthread_attr_destroy(&attr);
if (ret != 0) {
fprintf(stderr, "Error: pthread_attr_destroy\n");
}

return 0;
}

結果輸出如下,

1
2
stack size: 65536
foo

為什麼不是在 foo 裡用 pthread_attr_init 後再用 pthread_attr_getstacksize 取得 stack size 呢?
因為 pthread_attr_init 後再用 pthread_attr_getstacksize 取得 stack size 是系統預設的 stack size,不是你設定後的 stack size。

其它參考
pthread_attr_setstacksize(3) - Linux manual page
https://man7.org/linux/man-pages/man3/pthread_attr_setstacksize.3.html
线程堆栈大小 pthread_attr_setstacksize 的使用
https://blog.csdn.net/godleading/article/details/7997630

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ Linux pthread_attr_getstacksize 取得執行緒堆疊大小用法
C/C++ Linux/Unix 讓執行緒跑在指定 CPU 的方法 sched_setaffinity
C/C++ Linux/Unix pthread 建立多執行緒用法與範例
C++ std::thread 建立多執行緒用法與範例

mac 雙螢幕延伸模式的 dock 切換方法

本篇 ShengYu 紀錄 mac 雙螢幕延伸模式的 dock 切換方法,在使用 MacBook Pro 外接螢幕時會發現 dock 在原本的螢幕上,延伸螢幕上沒有 dock 可以使用,要使用時要還要滑移回原本螢幕,這樣有點不方便,原來 macOS 已經支援切換的方式,而且切換的方法還蠻人性方便的,接下來就來介紹一下這個切換的方法吧!

如果想要將 dock 切換到另一個延伸螢幕上的話,可以在另外一個螢幕上,將滑鼠游標移動到螢幕的底部,然後將滑鼠一直往下滑。

這時 dock 就會換到滑鼠那個螢幕裡了!原本螢幕的 dock 就會不見,顯示在延伸螢幕上。反之要切換回來的方法也是這樣。

以上就是 mac 雙螢幕延伸模式的 dock 切換方法介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
macOS Screen Sharing 用指令開啟螢幕分享
macOS 查詢 Xcode 版本的 3 種方法
macOS 安裝 zsh-completions 自動完成指令
macOS 版本升級的方法
macOS 安裝舊版的 Xcode 版本

grep 遇到 binary file (standard input) matches 解決方法

本篇 ShengYu 紀錄使用 grep 遇到 binary file (standard input) matches 的解決方法,某天使用 grep 時出現了 Binary file (standard input) matches 這樣的錯誤訊息,然後之後的 grep 就沒有東西了,看起來這個訊息是說 grep 從標準輸入讀取處理時遇到了 Binary file 二進制檔,但我很確定我是 cat 文字檔給 grep,那怎麼辦?

解決方法:
grep 使用 -a 選項(--text 選項也可),就是叫 grep 指令遇到 binary 就把它當文字處理,像這樣寫,

1
grep -a 'pattern'

所以我原本的指令是用 cat 把文字檔印出來再導給 grep 處理,

1
cat xxx.txt | grep 'pattern'

加了 -a 改寫後變成這樣,

1
cat xxx.txt | grep -a 'pattern'

這樣就搞定了!

其他參考
grep returns “Binary file (standard input) matches” when trying to find a string pattern in file - Unix & Linux Stack Exchange
https://unix.stackexchange.com/questions/335716/grep-returns-binary-file-standard-input-matches-when-trying-to-find-a-string

其它相關文章推薦
Linux 常用指令教學懶人包
Linux grep/ack/ag 搜尋字串用法與範例
Linux ag 搜尋字串用法與範例(比 grep 還快)
Linux cut 字串處理用法與範例
Linux sed 字串取代用法與範例
Linux find 尋找檔案/尋找資料夾用法與範例
Linux kill 指令砍掉指定的 process name

Shell Script 判斷檔案是否存在

本篇 ShengYu 介紹 Shell Script 判斷檔案是否存在的用法與範例。

以下 Shell Script 判斷檔案是否存在的用法介紹將分為這幾部份,

  • Shell Script 判斷檔案是否存在
  • Shell Script 判斷多個檔案是否存在

那我們開始吧!

Shell Script 判斷檔案是否存在

這邊示範用 Shell Script 來判斷 myfile.txt 檔案是否存在,判斷檔案要用 -f,如下範例,要注意 -f 前有個空格,因為使用 if 條件判斷語法 [ ] 中括號的兩端內側必須要有一個空白字元,

1
2
3
4
5
if [ -f myfile.txt ]; then
echo "Yes"
else
echo "No"
fi

判斷目錄/資料夾是否存在則是要用 -d

Shell Script 判斷多個檔案是否存在

這邊示範用 Shell Script 來判斷多個檔案是否存在,如果是要判斷兩個檔案都同時存在的話,可以用 && 連接條件式,範例如下,

1
2
3
4
5
if [ -f myfile1.txt ] && [ -f myfile2.txt ]; then
echo "Yes"
else
echo "No"
fi

如果要用 Shell Script 來判斷兩個檔案任一個檔案存在的話,可以用 || 連接條件式,範例如下,

1
2
3
4
5
if [ -f myfile1.txt ] || [ -f myfile2.txt ]; then
echo "Yes"
else
echo "No"
fi

如果要判斷 3 個檔案或 3 個以上的檔案是否同時存在,程式碼通常會比較長,
這時適時地換行就會比較好維護程式碼,範例如下,

1
2
3
4
5
6
7
if [ -f myfile1.txt ] && 
[ -f myfile2.txt ] &&
[ -f myfile3.txt ]; then
echo "Yes"
else
echo "No"
fi

以上就是 Shell Script 判斷檔案是否存在的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 Shell Script 相關技術,可以參考看看下面的文章,
Shell Script 新手入門教學
Shell Script 四則運算,變數相加、相減、相乘、相除
Shell Script if 條件判斷
Shell Script for 迴圈
Shell Script while 迴圈
Shell Script 讀檔,讀取 txt 文字檔