[C][Multi-Thread] How to use pthread_create and pthread_join to operate multi-thread

文章目錄
  1. Purpose
  2. Compiler
  3. Sample Code 1
  4. Sample Code 2

Purpose

今天在練習如何使用pthread_create和pthread_join來練習multi-thread的操作.

multi-thread 的code的好處, 在於你假如用multi-process 的話, CPU會在去多做context-switch,

整體的效能下降. 但是由於每個thread都共用相同的memory 大小區塊, 所以有可能造成

每個thread access 到其他人thread要用的資料, 底下有兩個sample code, 第一個sample code,

就出現這樣的錯誤.

Compiler

1
gcc main.c -lpthread -o main

由於pthread是在libpthread.so的lib裏面, 所以我們在compiler 的時候, 必須將pthread lib include 進去.

.c 檔裏面, 也記得要include pthread.h.

Sample Code 1

你可以從底下的結果看出一個奇特的現象,

我產生了10個thread, 但是印出thread id 的時候, thread id =5, 卻印了4次.

這代表, 我create thread 的時侯, 帶下去的thread id (i), 被其他thread access到了. 造成了這個問題,

修這個bug的最簡單方法, 可以參考Sample Code 2.

關於 pthread_join 的使用, 也很單純.

他就wait 那裡,等待他要wait 的pthread id 被終止, 假如沒有終止的話, 那就GG了, 系統就會hang在那裏.

main.c

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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define THREAD_NUM 10
#define SR_DBG(fmt,arg...) printf("[%s][%d] "fmt, __FUNCTION__,__LINE__, ##arg)

void* thread_routine(void* argv)
{
int my_id = *((int*)argv);
SR_DBG("hello, i'm new thread, my name is id[%d] \r\n",my_id);
return;
}

int create_multi_thread_test(void)
{
int i;

pthread_t thread_id_array[THREAD_NUM];

for (i=0; i<THREAD_NUM; i++)
{
if (0 != pthread_create(&thread_id_array[i], NULL, thread_routine, &i))
{
SR_DBG("OMG, create thread FAILLL!!! \r\n");
}
}

for (i=0; i<THREAD_NUM; i++)
{
SR_DBG("Wait for termination of thread id [%d] \r\n", i);
if (0 != pthread_join(thread_id_array[i], NULL))
{
SR_DBG("OMG, Mother thread cannot wait for thread id [%d]\r\n", i);
}
}


return 0;
}

void main(void)
{
SR_DBG("This is multi-thread test code \r\n");

if (-1 == create_multi_thread_test())
{
SR_DBG("the multi thread test is FAILLLLL!!! \r\n");
}

}

Result1

Sample Code 2

這個smaple code, 就是針對上面去做一些改良, 多用一個 array 來存要帶進去thread_routine 裏面的引數

避免被其他thread access 倒.但是這一定不是最佳的方法...

main_v2.c

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
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define THREAD_NUM 10
#define SR_DBG(fmt,arg...) printf("[%s][%d] "fmt, __FUNCTION__,__LINE__, ##arg)

void* thread_routine(void* argv)
{
int my_id = *((int*)argv);
SR_DBG("hello, i'm new thread, my name is id[%d] \r\n",my_id);
return;
}

int create_multi_thread_test(void)
{
int i;

pthread_t thread_id_array[THREAD_NUM];
int thread_i[THREAD_NUM];

for (i=0; i<THREAD_NUM; i++)
{
thread_i[i] = i;
if (0 != pthread_create(&thread_id_array[i], NULL, thread_routine, &thread_i[i]))
{
SR_DBG("OMG, create thread FAILLL!!! \r\n");
}
}

for (i=0; i<THREAD_NUM; i++)
{
SR_DBG("Wait for termination of thread id [%d] \r\n", i);
if (0 != pthread_join(thread_id_array[i], NULL))
{
SR_DBG("OMG, Mother thread cannot wait for thread id [%d]\r\n", i);
}
}


return 0;
}

void main(void)
{
SR_DBG("This is multi-thread test code \r\n");

if (-1 == create_multi_thread_test())
{
SR_DBG("the multi thread test is FAILLLLL!!! \r\n");
}

}

Result2

[C][Dynamic Array] Exercise to operate the dyanmic array

文章目錄
  1. 目的
  2. 結論
  3. Sample Code

目的

很久之前買了一本書, 有關於系統程式師的養成計劃, 但是一直沒有很他認真的實行...

哈, 最近又開始了新生活運動, 打算每個禮拜花一點時間upgrade一下技能, 已經打算

靠着寫程式過我下半生了, HA....今天看到了一個有趣的議題, 資料結構裏面有 雙向鏈結以及dynamic array 這種東西,

我沒學過自料結構,但是雙向鏈結在interview的時候, 常會被問, 但是 dynamic array 這個我還是第一次各聽到

(是不是很虛, 沒辦法, 小弟不是資工的...走一步算一步吧!!)

今天就花了時間, 學習了一下要如何操作 dynamic array...

結論

先來下個結論, 一開始我以爲dynamic array 是指array 可以動態的改變, 將底下的array, 大小改變...

1
int static_array[10];

但是我做了實驗, 發現是不行的(有錯的話, 請糾正我吧!!)

基本上就是透過 malloc 要一塊heap 的記憶體,然後再用 realloc 的方式, 去放大縮小你的heap空間.

底下的sample 主要做了底下這些事情. 一行一行做註解, 會殺了我...所以我列出concept, 讓入門人有個概念

  1. 我用一個structure --> DArray, 來當作動態的array. 主要就是操作裏面的data
  2. 這個sample code有讓array長大的api, 以及讓array所小的api, 可以參考.h 檔去追
  3. DArray 裏面有兩個siz, int array_size; --> data array 的大小 int allocated_array_size; --> 我們用 malloc 實際跟系統要的memory size
  4. 爲什麼要分兩個size呢, 原因是因爲跟記憶體有關, 你應該不會希望, 當我們要新增刪除一個member 就要 call一次 realloc 吧...這樣會造成你的memory不連續. 就失去了dynamic array 的好處之一...

Sample Code

main.c

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*******************************
* Purpose : Exercise to operate the dynamic array
* Arthur : Sheldon Peng
* Date : 2015/3/21
* */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"

#define SR_DBG(fmt, vargs...) printf("[%s][%d]" fmt, __FUNCTION__, __LINE__, ##vargs)

#define CHECK_NULL(PTR) if(!PTR) \
{printf("ERROR!! the pointer is NULL \r\n");}


static RET DArray_shrink(DArray* thiz, int shrink_size)
{
CHECK_NULL(thiz);
void* shrink_data = realloc((void*)thiz->data, shrink_size*sizeof(char));

if ( NULL!=shrink_data)
{
thiz->data = (char*)shrink_data;
thiz->allocated_array_size = shrink_size;
SR_DBG(" SHRINK size to %d \r\n", shrink_size);
}
else
{
SR_DBG("FAIL to realloc array \r\n");
return RET_FAIL;
}

return RET_SUCCESS;

}

RET DArray_delete(DArray* thiz, int index)
{
CHECK_NULL(thiz);

if (index > thiz->array_size)
{
SR_DBG(" ERROR to delete the dynamic array member beacuse the index is not belong into dynamic array \r\n");
return RET_FAIL;
}

// remove the member from the dynamic array
int i;
for (i=index;i<(thiz->array_size-1);i++)
{
thiz->data[i] = thiz->data[i+1];
}
thiz->array_size = thiz->array_size-1;

// Shrink the dynamic array if the pool size is enough to use .
int shrink_size = thiz->array_size + (thiz->array_size>>1);

if (shrink_size < thiz->allocated_array_size)
{
if ( RET_FAIL == DArray_shrink(thiz, shrink_size) )
{
SR_DBG("FAILLL to shrink the dynamic array \r\n");
}
}
}

static RET DArray_enlarge(DArray* thiz, int enlarge_size)
{
CHECK_NULL(thiz);
void* enlarge_data = realloc((void*)thiz->data, enlarge_size*sizeof(char));

if ( NULL!=enlarge_data )
{
thiz->data = (char*)enlarge_data;
thiz->allocated_array_size = enlarge_size;
SR_DBG(" ENLARGE size to %d \r\n", enlarge_size);
}
else
{
SR_DBG("FAIL to realloc array \r\n");
return RET_FAIL;
}

return RET_SUCCESS;
}

RET DArray_insert(DArray* thiz, int index, char insert_data)
{
CHECK_NULL(thiz);

if (index > thiz->array_size)
{
SR_DBG("Your index is wrong, because the index is not wihin the array \r\n");
return RET_FAIL;
}

if (thiz->allocated_array_size < thiz->array_size+1)
{
SR_DBG("Because the space is not enough, so we need to enlarge the space for dynamic array \r\n");
int enlarge_size = (thiz->array_size>>1) + thiz->array_size;
if (RET_FAIL == DArray_enlarge(thiz, enlarge_size ))
{
SR_DBG("FAILLL to enlarge the space of dynamic array \r\n");
return RET_FAIL;
}
}

int i;
for ( i=thiz->array_size; i>index; i--)
{
thiz->data[i] = thiz->data[i-1];
}

thiz->data[index] = insert_data;
thiz->array_size = thiz->array_size+1;
}

void Display_DArray(DArray* DArray_ptr)
{
int i;
int size = DArray_ptr->array_size;

SR_DBG("My Dynamic Array is : \r\n");
SR_DBG("size is %d \r\n", size);
SR_DBG("allocated size is %d \r\n", DArray_ptr->allocated_array_size);

for ( i=0; i<size; i++)
{
printf("%d, ", DArray_ptr->data[i]);
}
printf("\r\n");
}

void main(void)
{
// Init my dynamic array
DArray myDArray;
myDArray.array_size = MINIMUN_ARRAY_SIZE;
myDArray.allocated_array_size = MINIMUN_ARRAY_SIZE+ (MINIMUN_ARRAY_SIZE>>1);

//char InitArray[myDArray.array_size];
myDArray.data = (char*)malloc(sizeof(char)*myDArray.array_size);
memset((void*)myDArray.data, 0x0, (myDArray.array_size)*sizeof(char));

// Display all dynamic array members.
Display_DArray(&myDArray);

// test
SR_DBG("======== TEST for ENLARGing D_ARRAY \r\n");
int i;
for (i=0;i<10;i++)
{
DArray_insert(&myDArray, 0, i);
}

for (i=0;i<10;i++)
{
DArray_insert(&myDArray, 5, i);
}
Display_DArray(&myDArray);
SR_DBG("======== TEST for SHRINking D_ARRAY \r\n");
DArray_delete(&myDArray, 1);
DArray_delete(&myDArray, 1);
DArray_delete(&myDArray, 1);
DArray_delete(&myDArray, 1);
DArray_delete(&myDArray, 5);
DArray_delete(&myDArray, 6);
Display_DArray(&myDArray);
}

main.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define MINIMUN_ARRAY_SIZE 1

typedef enum
{
RET_SUCCESS,
RET_FAIL,
}RET;

typedef struct _DArray
{
int array_size;
int allocated_array_size;
char* data;
}DArray;

RET DArray_insert(DArray* thiz, int index, char insert_data);
RET DArray_delete(DArray* thiz, int index);

[C][uinstd] 簡易使用 readlink

文章目錄
  1. 目的
  2. Sample Code

目的

最近遇到一個問題, 假如我希望我的程式能夠知道某個symbolic link 的指向.

但是我又不希望用 fork+exec or system 的方式, 去產生另一個process 來執行"ls -l"

直接單純的使用 uinstd.h 裏面的readlink來得到link的指向.

看起來fork+exec 的比較有趣困難 XDD, 過幾天再寫一下心得...哈

Sample Code

1. 產生一個symbolic link

什麼是symbolic link呢?熟稱soft link, 有點像windows 底下的聯結, google一下巴...

1
sheldon$ ln -s ~/python link_test

我產生了一個link 稱作link_test, 這個link指向 ~/python

2. example code

main.c

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
//*****************************
// Purpose : this is an sample code to use the api of readlink
// Arthur : Sheldon Peng
// Date : 2015/3/18
//***************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

void main(void)
{
char link_path[] = "/home/sheldon/programming/c_language/readlink/link_test";
char target_path[256];
memset(target_path, 0, sizeof(target_path));

if ( -1 == readlink(link_path, target_path, sizeof(target_path)))
{
printf("Fail to read link path !!\r\n");
}▫
else
{
printf("link path is %s \r\n", target_path);
}

}

[QT][GUI][Ubuntu] Hello World !

文章目錄
  1. 目的
  2. Sample Code
  3. How to compile QT program by command line

目的

最近在學習用QT這個third party 來寫GUI界面.

之前有用過 QT creator 這個IDE, 用拖曳的方式產生GUI 的component

用起來挺順手的. 但是整個project 怎麼生出來的, .pro 檔市幹嗎用的, qmke 和make有什麼差異

完全不清楚在做什麼. 所以今天花了一點時間, 查了要如何透過command line的方式

一步一步的靠近. 我參考這篇

Sample Code

qt_demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <QApplication>
#include <QLabel>
#include <QWidget>

int main(int argc, char* argv)
{
QApplication app(argc, argv);
QLabel hello(<center>This is my first QT hello world!!</center>);
hello.setWindowTitle("My First Qt Program");
hello.resize(400,400);
hello.show();
return app.exec();
}

How to compile QT program by command line

1. copy qt_demo.cpp to your directory.

1
cp qt_demo.cpp [your directory]

2. generate the .pro file for QT project setting

1
qmake -project

3. 將你程式需要的QT module, 放到 .pro file (前一步, 產生出來的)

底下是將 core gui widgets 這三個加入要用的module list 裡面. 當 compiler 要做compile/link 的時候, 才會找得到.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
######################################################################
# Automatically generated by qmake (3.0) ?? 3? 15 16:33:14 2015
######################################################################

TEMPLATE = app
TARGET = qt_tutorial
INCLUDEPATH += .


QT += core gui
QT += widgets

# Input
SOURCES += qt_demo.cpp

4.利用qmake 指令, 將make 產生出來

1
qmake

你會發現, 你現在這個folder 底下, 會產生一個make 檔

5. Compile

就直接下 make 囉!!! 就會產生一個執行檔.

6. 成果

1
./qt_tutorial

這樣就產生了hello world 了.., 假如要省事的話,

還是用qt creator 吧... kerker

[C][ELF] Attribute Section

文章目錄
  1. 目的
  2. Background
  3. 快接近重點了XDD
  4. 來驗證看看囉!!

目的

這幾天看到有人的code, 在資料或是function前面多加 attribute 的關鍵字

所以很好奇, 這東東是幹什麼用的. 花了一點時間讀了相關的blog, 自己消化了一下, 寫了測試的code, 來驗證一下.

自定section 的目的, 應該是要提高cache 的使用效率. 這樣的話, 但是相對的

你要code size會變大, 畢竟你多了section header 的資料.

Background

在開始前可能要先明白什麼叫做section, 什麼是objuct code, 什麼ELF檔,

objuct code 就是我們.c 檔compiler 過後的檔案, 假如在透過linker 的話,

就會將所有的.o檔, reloate 成elf.

一個.o 檔其實就可以把他拆解成許多的section. 相同特性的資料, 就會擺成相同的secion上面.

那我們是否可以自定自己的section 呢, 答案是可以的, 讃阿~~

就是透過attribute 來告知compiler, 我要自定自己的section.

快接近重點了XDD

首先我寫了一個程式, 兩個file, 每個file, 任一個function.

其實只是去印 global array 的值, 只是我將 int_array 放到我自定的section當中,

我取名成 .sheldon.data

main.c

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
//***********************
// Arthur : Sheldon Peng
// date : 2015/03/12
//************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define array_size 5
__attribute__((section(".sheldon.data"))) int int_array[array_size] = {0,1,2,3,4};

char test_bss[1024];

void main(void)
{
int size = array_size;
int_array[size-1] = 5;

memset(test_bss, 'a', sizeof(test_bss));

printf("Hello, this is attribute section test \r\n");
extern void printf_array(int*,int);
printf_array(int_array, size);
}

printf_array.c

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

void printf_array(int* ptr, int size)
{
printf("[%s] \r\n", __FUNCTION__);
int i = 0;
for (i=0; i<size; i++)
{
printf("%d, ", ptr[i]);
}
printf("\n done \n");
}

常用指令

  1. readelf -s : 讀這個elf/object 的symbol
  2. readelf -S : 讀這個elf/object 的Section
  3. readelf -a : 讀所有的資訊

來驗證看看囉!!

先將兩個 .c 檔個別的compiler

1
2
3
gcc -c print_array.c              // 產生 print_array.o (object)
gcc -c main.c // 產生 main.o (object)
gcc main.o print_array.o -o main // 產生 main (elf)

透過下 readelf -S 來觀察自定的section.

是不是多了 .sheldon.data XDD

其實還有非常多東西可以看, 像是還沒link前的symble 有什麼不一樣.

某些default 的section各別代表什麼意義. 要如何找出, 你這個elf 有哪些dependency 的lib...

非常非常多, 我也搞的物煞煞. 哈, 所以就走一步算一步.

[C++][Virtual Function] Exercises

文章目錄
  1. 目的
  2. Exercise

目的

最近在練習基本的clss的用法, 突然想到一些問題.

  1. 我們利用關鍵字virtual 來使用extend 的function member 的時候, base class 是否需要有相同引數的function member?

    --> 答案是要的

  2. extend class 要如何存取 base class 的 member data

    --> 將base class的member data 從private 改成protected

  3. extend class 在用 virtual 關鍵字的時候, 是否需要在function 宣告的前面加上 virtual

    --> 不用

Exercise

底下是間單的測試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
//***********************************
//**********************************
// Arthur : Sheldon Peng
// Date : 2015.3.10
// Purpose : Try the understand the virtual function in C++
//*********************************
//**********************************

#include <iostream>
using namespace std;

class base_class
{
public :
base_class(void);
virtual void set_value(int);
virtual void set_value(int, int);
void print_value(void);

protected :
int v1;
int v2;
};

base_class :: base_class(void)
{
v1 = 0;
v2 = 0;
cout << "base_class constructor !!" <<endl;
}

void base_class :: set_value(int a)
{
cout << "base class to set_value1" <<endl;
v1 += a ;
}

void base_class :: set_value(int a, int b)
{
cout << "base class to set_value" <<endl;
v1 = 0;
v2 = 0;
}

void base_class :: print_value(void)
{
cout << "v1 = " << v1 <<endl;
cout << "v2 = " << v2 <<endl;
}

class extend_class : public base_class
{
public :
extend_class(void);
void set_value(int, int);
};

extend_class :: extend_class(void) : base_class()
{
cout << "extend clss constructor" << endl;
}

void extend_class::set_value(int a, int b)
{
cout << "extend class to set_value" <<endl;
v1 += a;
v2 += b;
}

int main(void)
{
base_class BC;
extend_class EC;

base_class* base_ptr;

// base class
base_ptr = &BC;
base_ptr->set_value(10);
base_ptr->print_value();

// extended class
base_ptr = &EC;
base_ptr->set_value(5, 5);
base_ptr->print_value();

return 0;
}

[C++][Virtual Function/Inherit] My Animal World

文章目錄
  1. 目的
  2. 練習

目的

最近爲了學習QT, 所以重新練習C++的程式, C++的精華就在於封裝、繼承、多型. 我寫了一個 My Animal World 來練習這些觀念. 這支程式也非常單純, 可以來記錄你養寵物的體重. 以及每天都喂他飼料的話, 他們的體重會變成幾公斤.

練習

1. main.h

我在main.h 裏面放了base class 以及 extended class.

分別帶表了動物和貓以及鼠鼠的屬性.

要注意底下的一些重點.

  1. overload 結構子
  2. virutal function的用法.
  3. 我把實作都放到.c 黨裏面了
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
//***********************************
//**********************************
// Arthur : Sheldon Peng
// Date : 2015.3.9
// Purpose : Try the understand the virtual function in C++
//*********************************
//**********************************

#define MAX_ANIMAL_NUMBER 2
enum {
BIG_CAT,
SMALL_NAUGHTY,
MAX_ANIMAL = MAX_ANIMAL_NUMBER,
};

class Animal
{
public :
Animal();
Animal(double,double);
void feed(int);
double get_weight(void);
double get_increase_per_day(void);
virtual void show_name(void);

private :
double weight;
double increase_per_day;
};

class Cat: public Animal
{
public :
Cat(double,double);
virtual void show_name(void);
};

class Mouse: public Animal
{
public :
Mouse(double,double);
virtual void show_name(void);
};

2.1 main.c

2.1 的部分, 我放了class 成員的實作, 很間單的體重以及增重的vlaue.

這裡很妙的是假如你 base和extended 有相同的member function (show_name)的話,

你又想使用extended class 的member function (show_name), 你可以在member function 加上virtual

假如你只想用base class的member function, 就把virtual 去除掉吧.

底下這個範例是留下virtual, 畢竟我想要每個動物東有自己的名字XDDD

我這邊還多定義了一個 pointer array 是放所有的動物的pointer.

這樣比較好操作. 要注意, 宣告array的member , 我是用 base class的poiner (重要)

這樣就非常方便了. 我就可以利用base class pointer 來操作所有extend class. 讃拉!!

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
//***********************************
//**********************************
// Arthur : Sheldon Peng
// Date : 2015.3.9
// Purpose : Try the understand the virtual function in C++
//*********************************
//**********************************

#include <iostream>
#include "main.h"

using namespace std;

Animal* animal_list[MAX_ANIMAL_NUMBER];

Animal::Animal()
{
cout << "This is First Animal constructor" << endl;
}

Animal::Animal(double weight_value, double increase_per_day_value)
{
weight = weight_value;
increase_per_day = increase_per_day_value ;
cout << "This is Second Animal constructor" << endl;
}

void Animal::feed(int food)
{
for (int i=0;i<food;i++)
{
weight += increase_per_day;
}
}

double Animal::get_weight(void)
{
return weight;
}

double Animal::get_increase_per_day(void)
{
return increase_per_day;
}

void Animal::show_name(void)
{
cout << "Hello, I don't have name, please give me a name ." << endl;
}

Cat::Cat(double a,double b):Animal(a, b)
{
cout << "This is Cat's constructor" << endl;
}

void Cat::show_name(void)
{
cout << "Hello, My name is Lazy Cat ." << endl;
}

Mouse::Mouse(double a,double b):Animal(a, b)
{
cout << "This is Mouse's constructor ." <<endl;
}

void Mouse::show_name(void)
{
cout << "Hello, My name is Sweet mouse ." <<endl;
}

2.2 main.c (main function)

這是程式主題. 一開始會先init cat/mouse, 然後就進去while loop

等待主人詢問是否要餵食你的可愛動物 XDDD .

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
int main(void)
{
int type;
int food_value;

Animal* animal_ptr;
Cat cat(7,0.05);
Mouse mouse(0.05,0.001);
animal_list[BIG_CAT] = &cat;
animal_list[SMALL_NAUGHTY] = &mouse;

cout << " Welcom to my animal house " << endl;

do
{
cout <<" please chose the animal you want to feed " << endl;
cout <<" [0] for cat, [1] for mouse, [2] check the weight of all cute animals !!" << endl;
cin >> type ;

if (type == 0)
{
animal_ptr = &cat;
cout << " 喵喵 !!!" << endl;
animal_ptr->show_name();
}
else if (type == 1)
{
animal_ptr = &mouse;
cout << "唧唧 !!!" << endl;
animal_ptr->show_name();
}
else if (type == 2)
{
cout << "======體重表======="<<endl;

for (int i=0; i< MAX_ANIMAL_NUMBER; i++)
{
animal_ptr = animal_list[i];
animal_ptr->show_name();
cout << "我的重量是 " << animal_ptr->get_weight()<<"(kg)" <<endl;
}
cout << "==================="<<endl;
continue;
}
else
{
cout << " wow, qq, We don't have your animal !!" <<endl;
continue;
}

cout << " How many days you want to feed ?? " << endl;
cin >> food_value;
animal_ptr->feed(food_value);

}while(1);

return 0;
}

[Raspberry Pi] Socket Programming and GPIO

文章目錄
  1. 目的
  2. Demo on Youtube
  3. Source code.

目的

很久之前, 曾經做過 socket programming在樹梅派的應用. 也做了個demo影片留在youtube上, 當初只是好玩做做,沒想到有人需要source code. 我找了一下, 所以就放上來了,有興趣的可以看一下囉,沒意外的話,應該也是一個拼裝車XDDD

這個Demo 影片, 是讓樹梅派當client, 讓laptop 當server 收訊號. 因爲我只有一個樹梅派, 但是我又想模擬mutlit-client的情況, 所以我在laptop又多起一個task去送訊號給server.

Demo on Youtube

This demo tell how to control GPIO and send the data to server. About socket programming, server can receive the data from multi client.

Source code.

下載Download

1. server端

// sr_server.c

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
/*
Function : socket code for server
Arthur : SheldonRush Peng
Date : 2013/7/26
*/

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(int argc, char *argv[])
{
int connfd = 0, n = 0, listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;

char charBuff[1024];
char recvBuff[1024];
time_t ticks;

// init the data structure of serv_addr
memset(&serv_addr, '0', sizeof(serv_addr));
memset(charBuff, '\0', sizeof(charBuff));
memset(recvBuff, '\0', sizeof(recvBuff));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8998);

// assign the scket port to socket
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

listen(listenfd, 20);

while (1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

printf("%s %d \n", "server: connfd is", connfd);
ticks = time(NULL);
snprintf(charBuff, sizeof(charBuff), "%s\n", ctime(&ticks));
printf("server: %s\n", charBuff);

while ( (n = read(connfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
printf("server: read %d bytes \n", n);
printf("server: EOF = %d \n", EOF);
if ( fputs(recvBuff, stdout) == EOF)
{
printf("Error : Fputs error \n");
}
}

if (n < 0)
{
printf("Error : read errpr \n");
}
// write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}

2. Clinet 端

// main.c

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
/*
Function : Detect whether GPIO[17] is high or low
Arthur : Sheldon RUsh Peng
Date : 2013/7/27
*/

#include <wiringPi.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "sr_clinit.h"


#define False 0
#define True 0
#define pin 0 //GPIO[17]

int main(int argc, char *argv[])
{
int pin_value = False;
time_t current_time;
int count = 0;

if (argc != 4)
{
printf("Usage : %s <ip> <port> <station id> \n", argv[0]);
return 1;
}

if (-1 == wiringPiSetup())
exit(1);

// init GPIO[17] to be INPUT port
pinMode(pin, INPUT);

while (1)
{
current_time = time(NULL);
pin_value = digitalRead(pin);
if (True == pin_value)
{
count ++;
printf("\n\n%s\n", ctime(&current_time));
printf("Work station call help [%d] time\n", count);

if (0 != socket_clinit_main(argc,argv))
{
printf("cannot call help \n");
return 1;
}
sleep(5);
}
}
}

// sr_clinit.h

1
extern int socket_clinit_main(int argc, char *argv[]);

// sr_clinit.c

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
/*
Function : Socket code for clinit
Arthur : SheldonRush Peng
Date : 2013/7/26
*/

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include "sr_clinit.h"

int socket_clinit_main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char sendBuff[1024];

struct sockaddr_in serv_addr;

if (argc != 4)
{
printf("Usage : %s <ip> <port> <station id>\n", argv[0]);
return 1;
}

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Error : cannot create a socket\n");
return 1;
}
memset(sendBuff, '\0', sizeof(sendBuff));

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2]));

if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0 )
{
printf("%s \n" , " Error : cannot convert text to ip binary");
return 1;
}

if ( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
{
printf("Error : canot connect server\n");
}

printf("Clinit: Send data to server, station id = %d\n", atoi(argv[3]));
snprintf(sendBuff, sizeof(sendBuff), "hi Sheldon, I am station id [%d]\n", atoi(argv[3]));
printf("Clint: data is {%s}\n", sendBuff);
write(sockfd, sendBuff, strlen(sendBuff));

close(sockfd);
/*
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] =0;
if ( fputs(recvBuff, stdout) == EOF)
{
printf("Error : Fputs error \n");
}
}

if (n < 0)
{
printf("Error : read error \n");
return 1;
}
*/
return 0;
}

[Raspberry Pi] Demod_Video

文章目錄
  1. 以下是我以前所做的demo 影片, 由於之前有換過站台, 大部分東西沒留下來QQ, 只剩下youtube的影片, 列出來留作紀念XD...

以下是我以前所做的demo 影片, 由於之前有換過站台, 大部分東西沒留下來QQ, 只剩下youtube的影片, 列出來留作紀念XD...

1. [Raspberry Pi] Connedted with PCA9505 I2C IO Expander

2. [Raspberry Pi] Face Detection by OpenCV

3. [Raspberry Pi] Socket Programming and GPIO

This demon tell how to control GPIO and send the data to server. About socket programming, server can receive the data from multi client.

4. [Raspberry Pi ] [Cam Module]

5.[Raspberry Pi] Video Codec of OpenMAX

6. [Raspberry Demo] Control DHT22 and update data to google