0%

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

First Step

Buy a Raspberry Pi

Actually the link explains everything. I will note that something important and explain how to figure out some tricky problems.

Please following the steps.

Install GCC 7

1
2
3
4
5
6
7
git clone https://bitbucket.org/sol_prog/raspberry-pi-gcc-binary.git
cd raspberry-pi-gcc-binary
tar xf gcc-7.2.0.tar.bz2
sudo mv gcc-7.2.0 /usr/local
export PATH=/usr/local/gcc-7.2.0/bin:$PATH
echo 'export PATH=/usr/local/gcc-7.2.0/bin:$PATH' >> .bashrc
source .bashrc

Install Node

1
2
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

Install Avahi and other Dependencies

1
sudo apt-get install libavahi-compat-libdnssd-dev

Install Homebridge

1
sudo npm install -g homebridge

Use the following commaned if you got the permission problem.

1
gyp WARN EACCES user "root" does not have permission to access the dev dir "/root/.node-gyp/5.5.0"
1
2
sudo npm install -g --unsafe-perm homebridge
homebridge

Figure out some problems

You got the error message if you runs the homebridge command. I have a tricky solution. Please following the steps.

1
2
3
sudo rm -rf /usr/lib/node_modules/
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

Set up the configure and name /home/pi/.homebridge/config.json

1
2
3
4
5
6
7
8
{
"bridge": {
"name": "Homebridge",
"username": "FF:FF:FF:FF:FF:FF", // MAC address of Ethernet on Raspberry
"port": 51826,
"pin": "111-11-111" // Set up what you want to
},
}

Set up boot up

  • To save the following words and to name homebridge into /etc/default
1
2
3
4
5
6
7
# Defaults / Configuration options for homebridge
# The following settings tells homebridge where to find the config.json file and where to persist the data (i.e. pairing and others)
HOMEBRIDGE_OPTS=-U /var/lib/homebridge

# If you uncomment the following line, homebridge will log more
# You can display this via systemd's journalctl: journalctl -f -u homebridge
# DEBUG=*
  • To save the following words and to name homebridge.service into /etc/systemd/system/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=Node.js HomeKit Server
After=syslog.target network-online.target

[Service]
Type=simple
User=homebridge
EnvironmentFile=/etc/default/homebridge
# Adapt this to your specific setup (could be /usr/bin/homebridge)
# See comments below for more information
ExecStart=/usr/local/bin/homebridge $HOMEBRIDGE_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
  • Configuration
1
2
3
4
5
6
7
8
sudo useradd --system homebridge
sudo mkdir /var/lib/homebridge
sudo cp /home/pi/.homebridge/config.json /var/lib/homebridge/config.json
sudo chown -R homebridge:homebridge /var/lib/homebridge/
sudo systemctl daemon-reload
sudo systemctl enable homebridge
sudo systemctl start homebridge
journalctl -u homebridge

Open your Homekit on your iPhone or iPad

  • Import the homebridge into your Homekit

Plugins

  • homebridge-server
    MUST install the plugin that will helpful to install other plugins and management your homebridge
1
sudo npm install homebridge-server@latest -g

Add this snippet to your config.json:

1
2
3
4
5
6
7
{
"platform": "Server",
"port" : 8765,
"name" : "Homebridge Server",
"log" : "/var/log/homebridge-server.log",
"restart" : ""
}

Restart your service and open your browser http://raspberry-ip:8765

1
sudo systemctl restart homebridge

How to remote control the Homekit

Please set up Home Hub in your iPad

Enjoy your Smart Home

it’s a simple way to install vnc server. Don’t use default vnc server (Realvnc)
that is not compactable on mac since it need to activate license, however, I
haven’t a monitor to display.

1
$ sudo apt-get install tightvncserver

Now you can use build-in vnc client on mac.

  • open Finder and press ⌘+k
  • In the Server Address enter vnc:// followed by your computer name or IP address.

First, I got a problem that the taskbar disappeared when I remoted to vnc server.
I have had a tricky solution. to remove lxpanel and the taskbar is back.

1
rm -rf ~/.config/lxpanel/

When I used cmocka to write the unit test, the compiler alerts a error cast from pointer to integer of different size [-Werror=pointer-to-int-cast]. I have tried to write a unit code for running arm 32-bit and x64 machine however it was not working since I wrote the following code that was only working properly on x64.

1
assert_false(list_find(list, 11));

Let’s figure out the problem since the void pointer.

First try, I rewrite the code on arm 32-bit that convert the void pointer to integer. So that it was working on my raspberry. However it was not working on x64 machine. WTF.

1
assert_false((int)list_find(list, 11));

Since the size of void pointer on x64 is 64-bit and the size of integer is 32-bit. Now the compiler alerts me another error message. How to figure out the problem. Let’s use a type intptr_t. The magic that converts to suitable size on the platform. If you compile the code on x64, it will convert to unsigned long that is 64-bit. Otherwise it converts to int.

1
assert_false((intptr_t)list_find(list, 11));

To compile bluez on the raspberry that got the following message when to install libreadline-dev.

1
2
3
4
5
Setting up install-info (4.13a.dfsg.1-5ubuntu1) ...
dpkg: error processing install-info (--configure):
subprocess installed post-installation script returned error exit status 127
Errors were encountered while processing:
install-info

It’s a locale problem. You can modify the /etc/environment to correct locale. My solution modify /etc/environment to en_US.UTF-8 and use raspi-config to install en_US.UTF-8. One more thing, don’t forget to run locale-gen to generate locale profile. Reboot your system. All problem solved.

You got the ERROR: polls..AppleDouble (unittest.loader._FailedTest) when you run the unit test on Django. It means OSX create the .AppleDouble folders in your Django project.

$ find . -name .AppleDouble
./.vscode/.AppleDouble
./.AppleDouble
./__pycache__/.AppleDouble
./polls/templates/.AppleDouble
./polls/templates/polls/.AppleDouble
./polls/.AppleDouble
./polls/__pycache__/.AppleDouble
./mysite/.AppleDouble
./mysite/__pycache__/.AppleDouble

Delete all of .AppleDouble and the problems solved.

$ find . -name .AppleDouble | xargs rm -rf

Updated:
Best solution. You can disable to create .AppleDouble on OSX.

$ defaults write com.apple.desktopservices DSDontWriteNetworkStores true

Check out the reference

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
#include <stdio.h>
#include <unistd.h>
int Modulus(int iN, int iMod) {
int iQ = (iN/iMod);
return iN - (iQ*iMod);
}
char GetChar(int iGenerator, char cBase, int iRange) {
return (cBase + Modulus(iGenerator, iRange));
}
int main() {
char caRow[80];
int j = 7;
int k = 2;
int l = 5;
int m = 1;
while (1) {
int i = 0;
while (i < 80) {
if (caRow[i] != ' ') {
caRow[i] = GetChar(j + i*i, 33, 30);
}
// colour output -- green
printf("\033[32m%c", caRow[i]);
++i;
}
j = (j + 31);
k = (k + 17);
l = (l + 47);
m = (m + 67);
caRow[Modulus(j, 80)] = '-';
caRow[Modulus(k, 80)] = ' ';
caRow[Modulus(l, 80)] = '-';
caRow[Modulus(m, 80)] = ' ';
usleep(10000);
}
return 0;
}

有個傢伙回答的不錯,可以參考 知乎

大學在恐龍書學過很多,什麼哲學家問題,但由於工作多年,一直不需要太複雜的處理這問題,所以也沒真心比較差異,好像都可以用,但看來還是有些差異。

然後在查資料時,也看到一篇 文章,裡面提到 Multi-thread 避免使用 semaphore,這其實也是合理。semaphore 可以處理 Multi-process 問題,這功能還是比較強大的。

No shit, just following the code. OSX based on POSIX that it can’t use sem_init to initial the semaphore and it can’t use sem_destroy to destroy the semaphore, too.

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
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t *s;
int a, b, c;
void getA() {
sleep(10);
a = 3;
printf("a: %d\r\n", a);
sem_post(s);
pthread_exit("Thread is done");
}
void getB() {
sleep(5);
b = 10;
printf("b: %d\r\n", b);
sem_post(s);
pthread_exit("Thread is done");
}
void getC() {
sem_wait(s);
sem_wait(s);
c = a+b;
printf("c: %d\r\n", c);
sleep(10);
pthread_exit("Thread is done");
}
int main(int argc, char *argv[]) {
pthread_t tid1, tid2, tid3;
sem_unlink("s");
s = sem_open("s", O_CREAT, S_IRUSR | S_IWUSR, 0);
if(pthread_create(&tid1, NULL, (void*)getA, NULL)) {
}
if(pthread_create(&tid2, NULL, (void*)getB, NULL)) {
}
if(pthread_create(&tid3, NULL, (void*)getC, NULL)) {
}
pthread_join(tid3, NULL);
sem_close(s);
sem_unlink("s");
return 0;
}

I was refactoring the project because sometimes the project crashed. Analyzing the code I found it is the problem of memory managemnt. Sometime it use the wrong address when it free the memory. In the project, it didn’t use malloc of GNU C library to allocate the memory and it implemented the feature.

The following code is a basiclly malloc implementation from stackoverflow. It use sbrk to implement malloc. I was confusing why it use a low-level function to implement malloc allocating the memory. What is different with malloc and sbrk?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void* malloc(size_t size) {
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)sbrk(size);
block->size = size;

return ((char*)block) + sizeof(size_t);
}

What is different with malloc and sbrk?

sbrk is a low-level function in GNU C library. From wikipedia said that brk and sbrk are basic memory management system calls used in Unix and Unix-like operating systems to control the amount of memory allocated to the data segment of the process. sbrk supports to allocate the memory but it isn’t flexible to use memory that means it can’t use released memory. You can follow the code and I used static memory to refactor malloc. The code allocated a huge array and it retured the pointer address to new block if it wasn’t released memory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define MEM_SIZE 0x10000
static unsigned int mem_pool[MEM_SIZE];
static unsigned int offset = 0;

void* new_malloc(size_t size) {
unsigned int *p = mem_pool;
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)(p+offset);
block->size = size;
offset += size+1;

return ((char*)block) + sizeof(size_t);
}

Finally I can show you the implement code that what you want.

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
typedef struct free_block {
size_t size;
struct free_block* next;
} free_block;

static free_block free_block_list_head = { 0, 0 };
static const size_t overhead = sizeof(size_t);
static const size_t align_to = 16;
#define MEM_SIZE 0x10000
static unsigned int mem_pool[MEM_SIZE];
static unsigned int offset = 0;

void* new_malloc(size_t size) {
unsigned int *p = mem_pool;
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)(p+offset);
block->size = size;
offset += size+1;

return ((char*)block) + sizeof(size_t);
}

void new_free(void* ptr) {
free_block* block = (free_block*)(((char*)ptr) - sizeof(size_t));
block->next = free_block_list_head.next;
free_block_list_head.next = block;
}

void* new_realloc(void* ptr, size_t size) {
void *new_ptr;
new_ptr = new_malloc(size);
if (new_ptr == NULL) return NULL;
memcpy(new_ptr, ptr, size);
new_free(ptr);
return new_ptr;
}