0%

nvm:node.js版本管理工具安装

nvm是可以管理不同版本的node和npm,所以我们通过nvm来安装Node.js
nvm的Github地址[nvm][https://github.com/nvm-sh/nvm]

安装nvm

1
2
3
4
# cURL
$ curl https://raw.github.com/creationix/nvm/v0.33.11/install.sh | sh
# Wget
$ wget -qO- https://raw.github.com/creationix/nvm/v0.33.11/install.sh | sh

进入~/.nvm目录下配置环境

1
$ cd ~/.nvm/ && touch .bash_profile

向.bash_profile中写入如下内容

1
2
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

执行文件配置

1
$ source .bash_profile

这时候就安装成功了

1
nvm --version

安装Node.js

1
$ nvm install stable

安装hexo

npm是世界上最大的软件注册表,每个星期有30亿次下载量

npm设置为淘宝的镜像源

1
$ npm install -g cnpm --registry=https://registry.npm.taobao.org

安装hexo

1
$ cnpm install -g hexo-cli

在想要创建的文件夹下初始化hexo目录

1
$ hexo init

使用hexo

1
2
3
$ hexo s        # 启动hexo
$ hexo clean # 删除数据库
$ hexo g # update generate

然后就可以在浏览器地址栏中输入localhost:4000访问到博客了


部署到Github

通过部署到远端服务器来公开使用

在github上创建名为[你的ID.github.io]的项目

安装部署插件

1
$ cnpm install --save hexo-deployer-git

设置_config.yml

1
2
3
4
# Deployment下配置
type: git
repo: [your github repository url]
branch: master

部署到远端

1
$ hexo d

Hoex文档说明

Reference from codesheep

hexo-console-rename插件安装

  • Install hexo-console-rename
    1
    $ npm install hexo-console-rename@3 --save
  • Install org-mode
    1
    $ npm install https://github.com/CodeFalling/hexo-renderer-org#emacs --save
    _config.yml:
    1
    2
    3
    4
    5
    6
    org:
    emacs: '/usr/bin/emacs'
    common: |
    #+OPTIONS: toc:nil num:nil

    # new_post_name = org

1
2
3
4
5
6
7
8
9
10
11
12
13
// IEEE POSIX头文件

#include <pthread.h> // POSIX线程
#include <semaphore.h> // 信号量
#include <sys/sem.h> // 有名信号量(system v)
#include <sys/wait.h> // 进程控制
#include <unistd.h> // 符号常量
#include <sys/types.h> // 基本系统数据类型
#include <fcntl.h> // 文件控制
#include <sys/stat.h> // 文件状态
#include <sys/ipc.h> // IPC
#include <sys/shm.h> // XSI共享存储
#include <sys/msg.h> // XSI 消息队列
1
2
3
4
5
6
// ISO C
#include <assert.h> // 验证程序断言
#include <errno.h> // 出错码
#include <stdio.h> // 标准I/O库
#include <stdlib.h> // 实用函数
#include <signal.h> // 信号
1
2
3
4
5
6
7
// I/O

STDIN_FILENO // fd 0
STDOUT_FILENO// fd 1
STDERR_FILENO// fd 2

// read more to "Chapter_three.md"
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
// 创建线程标识
pthread_t thread_id;
// 创建互斥量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // static macro init
// 创建信号量
sem_t sem;
// 创建条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER // static macro init
// 创建消息队列
mqd_t mqd;
// 创建读写锁
pthread_rwlock_t rwlock;
// 创建自旋锁
pthread_spinlock_t spinlock;
// 创建屏障
pthread_barrier_t barrier;
// 创建文件锁对象
struct flock flck;
// 创建共享内存指针
caddr_t memptr;


// 线程属性
pthread_attr_t pat;
// 互斥量属性
pthread_mutexattr_t pmt;
// 读写锁属性(唯一属性是进程共享属性)
pthread_rwlockattr_t prt;
// 条件变量属性
pthread_condattr_t pct;
// 栅栏属性(目前只有进程共享属性)
pthread_barrierattr_t pbt;
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// 线程

// 创建线程
int pthread_create(pthread_t *thread,
const pthread_att_t *attr,
void *(*start_routine)(void *),
void *arg);
// success return 0; otherwise, return error number
// e.g. pthread_create(thread_id, NULL, (void *)func, (void *)&arg);

// 加入线程
int pthread_join(pthread_t thread,
void **retval);
// success return 0; otherwise, return error number
// e.g. error = pthread_join(pid, (void *)&err_func);

// 线程ID的比较
int pthread_equal(pthread_t t1, pthread_t t2);
// success return non-zero value; otherwise, return 0

// 线程的取消
int pthread_cancel(pthread_t thread);
// success return 0; othwrwise, return error number

// 分离线程
int pthread_detach(pthread_t thread);
// success return 0; otherwise, reutrn error number

// 退出线程
void pthread_exit(void *retval);

// 发送信号给线程
int pthread_kill(pthread_t thread, int sig);
// success return 0; otherwise, return error number and no signal to send

// 取得目前线程标识
pthread_t pthread_self(void);
// always succedds, return the calling thread's ID

// 线程让步
int pthread_yield(void);
// success return 0; otherwise, reutrn error number

// pthread接口允许通过设置每个对象关联的不同属性来细调线程和同步对象的行为
// e.g. 线程栈:虚地址空间大小是固定的,因为进程中只有一个栈.而它被所有线程栈共享.
// e.g. 如果许多线程的线程栈累计超过可用的虚地址空间,就要减少栈大小.如果调用函数涉及很深的栈帧就要调大

// 线程属性的初始化
int pthread_attr_init(pthread_attr_t *attr);
// success return 0; otherwise, return error num

// 线程属性销毁
int pthread_attr_destroy(pthread_attr_t *attr);
// success return 0; otherwise, return error num

// 注册fork句柄??
int pthread_atfork(void (*prepare)(void),
void (*parent)(void),
void (*child)(void));
// success return 0; otherwise, return error num
// e.g. 可以用来解决线程与fork的问题,比如用来清除锁状态,通过调用此函数建立fork处理程序

// 线程栈最小长度(字节数)
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);

// 线程栈的分离状态属性
// PTHREAD_CREATE_JOINABLE(非分离状态) | PTHREAD_CREATE_JOINABLE(分离状态)
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
// e.g. 非分离线程在终止后,必须有一个线程用join来等待他,否则会资源泄露

// 线程栈末尾的境界缓冲区大小(字节数)
// e.g. guardsize的值向上舍入为PAGESIZE的倍数
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
// e.g. 溢出保护会浪费系统资源,如果创建大量线程,并已知线程不会溢出,那么关闭溢出保护区可以节省系统资源

// 线程栈的最低地址
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr);
// success return 0; otherwise, return error num



// 互斥引用对象的初始化
int pthread_mutex_init(pthraed_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
// success return 0; otherwise, return error number
// e.g. pthraed_mutex_init(&mutex, NULL);

// 互斥引用对象的销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
// success return 0; otherwise, return error number

// 互斥量上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
// success return 0; otherwise, return error number

// 互斥量解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// success return 0; otherwise, return error number

// 互斥量属性初始化
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
// success return 0; otherwise, return error number
// e.g. 如果进程共享互斥量属性设置位PTHREAD_PROCESS_SHARED,多个进程之间的内存数据块互斥量就可以用于进程同步

// 读写锁也叫共享互斥锁.当读写锁是写加锁状态时,解锁前,所有试图对这个锁加锁的线程都会被阻塞.当读写锁是读加锁状态,所有试图读模式对它加锁的线程都可以得到访问权.
// e.g. 读写锁使用前必须初始化,释放内存前必须销毁

// 读写锁初始化
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
// success return 0; otherwise, return error number
// e.g. pthread_rwlock_init(&rwlock, NULL);

// 读写锁摧毁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
// success return 0; otherwise, return error number

// 锁上写锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock,
const struct timespec *restrict abs_timeout);
// success return 0; otherwise, return error number
// e.g. 带超时的锁获取锁失败将返回TIMEOUT

// 锁上读锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timerdlock(pthread_rwlock_t *restrict rwlock,
const struct timespec *restrict abs_timeout);
// success return 0; otherwise, return error number
// e.g. 带超时的锁获取锁失败将返回TIMEOUT

// 读写锁解锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
// success return 0; otherwise, return error number



// 线程等待条件
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
// success return 0; otherwise, return error number
// e.g. pthread_cond_wait(&cond, &mutex);

// 单独发送condition
int pthread_cond_signal(pthread_cond_t *cond);
// success return 0; otherwise, return error number

// 广播发送condition
int pthread_cond_broadcast(pthread_cond_t *cond);
// success return 0; otherwise, return error number

// 自旋锁跟互斥锁很相似,都是为了解决资源互斥使用.区别是互斥锁相当于只有0/1状态的信号量,当资源被占用,资源申请者将被阻塞,而自旋锁不会引起睡眠,而是不断循环空转

// 自旋锁的初始化
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
// success return 0; otherwise, return error number
// e.g. 单进程可以设置pshared参数为PTHREAD_PROCESS_SHARED

// 自旋锁加锁
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
// success return 0; otherwise, return error number

// 自旋锁解锁
int pthread_spin_unlock(pthread_spinlock_t *lock);
// success return 0; otherwise, return error number

// 自旋锁摧毁
int pthread_spin_destroy(pthread_spinlock_t *lock);
// success return 0; otherwise, return error number

// 屏障(barrier)是用户协调多个线程并行工作的同步机制.屏障允许每个线程等待,直到所有合作线程都达到某一点,然后从该点继续执行. (fence | 栅栏?)

// 屏障对象初始化
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
const pthread_barrierattr_t *restrict attr,
unsigned count);
// success return 0; otherwise, return error number
// e.g. pthread_barrier_init(&barrier, NULL, thread_num);

// 屏障对象摧毁
int pthread_barrier_destroy(pthread_barrier_t *barrier);
// success return 0; otherwise, return error number

// 在栅栏中同步
int pthread_barrier_wait(pthread_barrier_t *barrier);
// success return PTHREAD_BARRIER_SERIAL_THREAD or 0; otherwise, return error number
// e.g. 当调用pthraed_barrier_wait的线程在屏障技术count未满足条件时,进入休眠,直到满足所有吸线程被唤醒
1
2
3
4
5
6
7
8
9
// 基本类型

// 进程或进程组ID
pid_t pid;
// 对象(如字符串)长度(不带符号的)
size_t st;
// 返回字节计数的函数(带符号的)
ssize_t sst;
//
ELF文件信息
ELF头
程序头表
.init 节
.text 节
.rodata 节
.data 节
.bss 节
.symtab 节
.debug 节
.line 节
.strtab 节
节头表
1
2
3
4
5
6
7
8
9
10
11
// 进程

// 概念
// 孤儿进程:fork编程时,对于父进程已经终止的所有进程,它们的父进程都改变为init进程
// 僵尸进程:fork编程时,如果子进程先于父进程退出,就会处于终止状态,kernel为每个子进程保留了一定的信息(进程ID\终止状态\使用CPU事件总量等).
// 当父进程调用wait或waitip时得到这些信息,并将终止子进程从系统进程表删除,释放终止状态.如果没有获取子进程终止状态,进程表信息不会被移除,那么这些进程就会变成进程表中的僵尸进程.
// 预防措施有两大类型:
// 第一种是让父进程去通知系统,告诉系统它对子进程的终止没有任何兴趣:
signal(SIGCHLD, SIG_IGN); // in parent: ignore notification
// 第二种是在子进程终止时,让父进程执行一个wait.等待子进程终止
wait(NULL);
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
// 取得目前进程标识
pid_t getpid(void);
// 取得目前进程父进程标识
pid_t getppid(void);
// 从已存在的进程中创建新进程
pid_t fort(void);
/*
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child.
On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
*/

// 执行程序
int main(int argc, char *argv[], char *envp[]);
int execl(const char *path, const char *arg, ...);
int execve(const char *path, char const *arg[], char *const envp[]);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
// error return -1
// e.g. execve函数的功能是在当前进程上下文中加载并运行一个新程序
// p=filename | l=list | v=vector | e=environment
// e.g. execlp("ps", "ps", "-ef", NULL); // artv[0] = ps
/* e.g.
{
char *argv[] = {"ps", "-ef", NULL);
execvp("ps", argv);
}
*/

// 终止进程
void exit(int status);
void _exit(int status);
// e.g. exit()与_exit()的区别在于,前者在调用exit系统调用前,还会调用退出处理函数和清除I/O缓冲
// e.g. 可以在父进程中利用wait(&status)来提取执行完的终止状态status并分析

// 等待子进程停止或中断
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid,
int *stat_loc,
int options);
// using WNOHANG and no sub process exit return 0, otherwise, success return >0 and error return -1
// e.g. pr = waitpid(status, NULL, WNOHANG);
// WNOHANG: 如果没有结束的子进程马上返回,不等待;
// WUNTRACED: 如果子进程暂行则返回,结束状态不理会
// 0: 同wait(),阻塞父进程,直到退出
// wait macros evaluate
WIFEXITED(stat_val); // wait if exited
// evaluate to a non-zero for a child process
WEXITSTATUS(stat_val); // wait exit status
// if WIFEXITED is non-zero, evaluate to the status argument that the child process passed to _exit() or exit() or return from main().
// e.g. if (WIFEXITED(status)) status = WEXITSTATUS(status);
WIFSIGNALED(stat_val); // wait if signaled
WTERMSIG(stat_val); // evaluate to the wait WIFISNALED number of the signal
WIFSTOPPED(stat_val); // wait if stopped
WSTOPSIG(stat_val); // evaluate to the WIFSTOPPED nmber of the signal
WIFCONTINUED(stat_val); // wait if continued, evaluate to a non-zero value if status has continued from a job control stop.
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
// 进程间通道

// 创建管道
int pipe(int fildes[2]);
// success return 0. otherwise, return -1 and set errno
// e.g. 管道主要是用于不同进程间的通信,通常是先创建管道再fork一个子进程,因为子进程会继承父进程创建的管道
// e.g. 管道是单工工作方式,要么读要么写.虽然父子进程都有读写端,但只能使用一个,因此需要把不适用的读或写端文件描述符关闭.
// e.g. pipe读端存在时,写入数据才有意义,否则向pipe写入数据的进程会受到kernel传来的SIGPIPE signal(Broken Pipea error norrmally)
// e.g. 写数据时,不保证写入原子性,只要缓冲区有空间,就会尝试写,如果缓冲区满,写操作就会阻塞

// 创建FIFO有名管道
int mkfifo(const char *pathname, mode_t mode);
// success return 0. otherwise, return -1 and set errno
// e.g. mkfifo("fifofile", 0644);

// 发送信号
int kill(pid_t pid, int sig);
int raise(int sig); // 向自身进程发起 相当于kill(getpid(), sig);
// success return 0. otherwise, return -1 and set errno
pid = 0+; // 发送信号给pid
pid = 0; // 发送信号给当前进程同进程组的进程
pid = -1; // 发送信号给所有进程表中的进程
pid = -1- // 发送信号给进程组号为-pid的每个进程
SIGINT // Ctrl + c
SIGQUIT // Ctrl + \
SIGKILL // 结束程序不能阻塞、处理和忽略
SIGALARM // 当定时器到时发出
SIGSTOP // 暂停进程,同SIGKILL不能忽视
SIGTSTP // Ctrl + z
// man 7 signal

// 设置一个定时器
unsigned alarm(unsigned seconds);
// success return SIGALRM signal. otherwise, return 0

// 挂起进程
int pause(void);

// 发送信号至处理函数
void (*signal(int sig, void (*func)(int)))(int);
// e.g. void exec_handler(int signo);
// e.g. signal(SIGINT, exec_handler); // 通过signo来判断状态
// e.g. signal(SIGTSTP, SIG_IGN); // 忽略改信号

// 检查或修改信号的处理动作(action)
int sigaction(int sig,
const struct sigaction *restrict act,
struct sigaction *restrict oact);
// success return 0. otherwise return -1 and set errno
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
172
173
174
175
176
177
178
// POSIX IPC
struct mq_attr {
long mq_flags; /* Flags: 0 or O_NONBLOCK */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue */
};
// 共享文件

// flock结构体的初始化 e.g.
struct flock lock;
lock.l_type = F_WRLCK; // read/write lock
lock.l_whence = SEEK_SET; // base for seek offsets
lock.l_start = 0;
lock.l_len = 0; // 0 here means until EOF
lock.l_pid; // proces id
// 文件控制
int fcntl(int fildes, int cmd, ...);
// Upon successful completion, the value returned shall depend on cmd as follows
// e.g. struct flock lock; fcntl(fd, F_SETLK, &lock);
F_DUPFD // return a new file descriptor
F_GETFD // get the file descriptor flags
F_SETFD // set the file descriptor flags
F_GETFL // get the file status flags and file access modes
F_SETFL // set the file status flags
F_GETOWN // if fildes refers to a socket, get the process or process group ID specified to receive SIGURG signals when out-of-band data is available
F_SETOWN // set
F_GETLK // get the lock bolcks description point to by the third argument
F_SETLK // set or clear file segment
F_SETLKW // wait setlk
F_UNLCK


// message queue
#include <mqueue.h>

// 创建或打开消息队列
mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag,
mode_t mode, struct mq_attr *attr);
// success return message queue descriptor. otherwise, return -1
// e.g. mqd_t mqd = mq_open("/temp.mq", O_RDWR);

// 关闭消息队列
int mq_close(mqd_t mqdes);
// success return 0. otherwise, return -1

// 删除消息队列
int mq_unlink(const char *name);
// success return 0. otherwise, return -1

// 设置消息队列属性
int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
// success return 0. otherwise, return -1
// e.g. mq_getattr("/temp.mq", &attr);

// 获取消息队列属性
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
// success return 0. otherwise, return -1

// 发送消息到消息队列
int mq_send(mqd_t mqdes, const char *msg_ptr,
size_t msg_len, unsigned msg_prio);
int mq_timedsend(mqd_t mqdes, const char *msg_ptr,
size_t msg_len, unsigned msg_prio,
const struct timespec *abs_timeout);
// success return 0. otherwise, return -1
// e.g. mq_send的prio优先级必须小于MQ_PRIO_MAX
// e.g. mq_send("/temp.mq", "hello", 5, 1);

// 接收消息从消息队列
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
size_t msg_len, unsigned *msg_prio);
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr,
size_t msg_len, unsigned *msg_prio,
const struct timespec *abs_timeout);
// success retunr number of bytes. otherwise, return -1
// e.g. mq_receive("/temp.mq", buf, buf_len, &msg_prio);

// 当消息有效时通知(异步事件)
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
// semaphore
#include <semaphore.h>

// 初始化和打开有名信号量
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
// success return address of the new semaphore; otherwise, return SEM_FAILED, and set errno
// e.g. sem_t *semptr = sem_open(SemaphoreName, O_CREAT, 0644, 0);

// 有名信号量退出
int sem_close(sem_t *sem);
// success return 0; otherwise, return -1 and set errno

// 有名信号量移除
int sem_unlink(const char *name);
// success return 0; otherwise, return -1 and set errno

// 无名信号量初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
// success return 0; otherwise, return -1 and set errno
// e.g. sem_init(&sem, 0, 1); init 1

// 销毁一个无名信号量
int sem_destroy(sem_t *sem);
// success return 0; otherwise, return -1 and set errno

// 信号量P操作
int sem_wait(sem_t *sem);
// success return 0; otherwise, semaphore value is left unchanged, return -1 and set errno

// 信号量尝试P操作
int sem_trywait(sem_t *sem);
// success return 0; otherwise, semaphore value is left unchanged, return -1 and set errno

// 信号量带超时的P操作
int sem_timedwait(sem_t *sem,
const struct timespec *abs_timeout);
// success return 0; otherwise, semaphore value is left unchanged, return -1 and set errno

// 信号量V操作
int sem_post(sem_t *sem);
// success return 0; otherwise, semaphore value is left unchanged, return -1 and set errno

// 信号量值的获取
int sem_getvalue(sem_t *sem, int *sval);
// success return 0; otherwise , return -1 and set errno

// shared memory segment
#include <sys/mman.h>

// 创建或打开POSIX共享内存对象
int shm_open(const char *name, int oflag, mode_t mode);
// success return a nonnegative file descriptor. otherwise, return -1.
// e.g. int fd = shm_open(filename, O_RDWR, 0644);
// e.g. 调用shm_open函数,此时,没有内存对象被分配.

// 分离共享内存
int shm_unlink(const char *name);
// success return 0. otherwise , return -1
// e.g. shm_unlink(filename);

// 将文件截断到指定长度
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
// success return 0. otherwise, return -1 and set errno
// e.g. ftruncate(fd, 512);

//
fstat

// 将文件或设备映射到内存
void *mmap(void *addr, // if addr is NULL, then the kernel chooses the address at which to create the mapping
size_t length, // how many bytes
int prot, // access protections
int flags, // mapping visible to other processes
int fd, // file descriptor
off_t offset); // offset
// success return a pointer to the mapped area. otherwise, return MAP_FAILED and set errno
// e.g. caddr_t memptr = mmap(NULL, ByteSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// e.g. 将指定文件fd中偏移量offset开始的长度为length个字节的一块信息映射到虚拟空间中起始地址为addr,长度为length个字节的一块区域
// prot(制定区域内页面的访问权限位,vm_area_struct中vm_flag字段)
PROT_EXE // pages页由指令组成
PROT_EXEC // pages may be executed(可执行)
PROT_READ // pages may be read(可读)
PROT_WRITE // pages may be written(可写)
PROT_NONE // pages may not be accessed(区域内页面不能被访问)
// flags(制定所映射的对象的类型,vm_area_struct结构中vm_flag字段)
MAP_SHARED // shared this mapping(共享对象,对应共享库文件中的信息)
MAP_PRIVATE // create a private copy-on-write mapping(私有对象,采用写时拷贝技术,对应可执行文件中只读代码区域(.init、.text、.rodata)和已初始化数据区域(.data)
MAP_ANON // 请求0的页,对应内核创建的匿名文件,相应页框用0初始化并驻留内存
MAP_PRIVATE|MAP_ANON// 未初始化数据(.bss),堆和用户栈等对应区域


// 取消映射内存
int munmap(void *addr, size_t length);
// success return 0. otherwise, return -1 and set errno(probably to EINVCAL).
// e.g. munmap(memptr, ByteSize);
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
// system V IPC

// 将文件名或对象标识符转换为System V IPC键
key_t ftok(const char *pathname, int proj_id);
// success return the generated key_t value. otherwise, return -1 and set errno
// e.g. key_t key = ftok(PathName, ProjectId); // pathname=queue.h, projectid=123
// e.g. IPC对象标识符与文件描述符不同.文件描述符为当前进程最小可用文件描述符数组下标,IPC对象是系统全局的流水号,归零循环分配使用
// e.g. 让多个进程访问某个特定IPC对象需要一个外部键,一个IPC对象与键管关联.
// e.g. path是个文件名,函数的操作是,取文件的stat结构的st_dev和st_ino部分值,然后与参数ID第八位结合生成键值.他有一个ipc_perm结构体
// e.g. key为IPC_PRIVATE
// e.g. IPC接口过于繁杂,且不适用通用文件系统,不能使用IO监控函数select及poll函数操作IPC,且缺少资源回收机制

// message queue
#include <sys/msg.h>

// 获取XSI消息队列标识符
int msgget(key-t key, int msgflg);
// success return message queue identifier. otherwise, return -1 and set errno
// e.g. int qid = mesgget(key, 0666 | IPC_CREAT);

// XSI消息控制操作
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
// success IPC_STAT, IPC_SET, and IPC_RMID return 0. IPC_INFO or MSG_INFO operation returns the index of the highest used entry array recording. MSG_STAT operation return the identifier of the queue those index was given in msqid. otherwise return -1 and set errno
// e.g. msgctl(qid, IPC_RMID, NULL); // remove queue
// cmd
IPC_STAT // copy information msqid into the msqid_ds
IPC_SET // write the values of some members of the msqid_ds structure
IPC_RMID // remove the message queue
IPC_INFO // returns infomation about system-wide mq limits and parameters in the structure pointed to by buf.


// 发送消息
int msgsnd(int msgid,
const void *msqp,
size_t msgsz,
int msgflg);
// success return 0. otherwise, return -1 and set errno
// e.g. msgsnd(qid, &msg, sizeof(msg), IPC_NOWAIT);

// 接收消息
ssize_t msgrcv(int msgid,
void *msgp,
size_t msgsz,
long msgyp,
int msgflg);
// success return the number of bytes actually copied. otherwise return -1 and set errno
// e.g. msgrcv(qid, &msg, sizeof(msg), types[i], MSG_NOERROR | IPC_NOWAIT);

// semaphore
#include <sys/sem.h>

// 获取一个System V信号量
int semget(key_t key, int nsems, int semflg);
// success return value the semaphore set identifier. otherwise return -1 and set errno

// 信号量的控制操作
int semctl(int semid, int semnum, int cmd, ...);
// failure return -1 and set errno. otherwise return the system call returns a nonnegative value depending on cmd as follows.

// 信号量操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
// success return 0. otherwise return -1 and set errno

// shared memory segment
#include <sys/shm.h>

// 创建或打开共享内存
// IPC_PRIVATE或ftok的返回 | 共享内存区大小 | 同open函数权限位,可8进制表示
int shmget(key_t key, size_t size, int shmflg);
// success return a non-negative shared memory identifier. otherwise, return -1 and set errno
// e.g. shmid = shmget(IPC_PRIVATE, MSIZE, 0666);

// 共享内存的控制操作
// 共享内存标识符 | IPC_STAT(获取对象属性)/IPCSET(设置对象属性)/IPC_RMID(删除对象) | 用以执行保存设置属性
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
// success return 0. otherwise, return -1 and set errno
// e.g. shmctl(shmid, IPC_RMID, NULL);

// 共享内存附加操作
// 映射的共享内存标识符 | 将共享内存映射到地址(NULL系统自动完成) | 默认0,共享内存只读
void *shmat(int shmid, const void *shmaddr, int shmflg);
// success return data structure associated with the shmID and the segment's start address. otherwise, return -1 and set errno
// e.g. char *shm_addr = shmat(shmid, NULL, 0); // error return (void *)-1

// 共享内存分离操作
// 共享内存映射后地址
int shmdt(const void *shmaddr);
// e.g. 此函数仅用于共享内存区域和进程的地址空间分离, 并不删除共享内存本身.参数是调用shmat函数时的返回值.
// success return 0. otherwise, return -1 and set errno
// e.g. shmdt(shm_addr);

异步IO、共享内存、内存映射文件、内存锁定、实时性时钟和定时器、备选调度策略、实时性信号、消息队列、信号量