Linux应用开发
Linux平台c语言应用开发
1. linux文件底层系统调用
- open 获取一个文件描述符
- write
- read
- close
- 操作不区分文本,二进制
1 | int main(int argc, char *argv[], char *envp[]) |
2. 父子进程共享打开文件
- 父子进程共享文件偏移量
- 子进程可以访问父进程的文件
- 多个进程指向同一个struct file,需要在每个文件close
- 若先fork后打开文件,不会指向同一个struct file,每个进程有自己独立的struct file
1 | int main(int argc, char *argv[], char *envp[]) |
3. 系统调用和库函数区别
- 系统调用在内核中,属于内核空间;库函数的实现在库函数中,属于用户空间
- 某些库函数底层其实仍然是系统调用
4. 内存申请与释放
- malloc()申请1G内存能否成功?
- malloc(单位是b)
- malloc申请的内存是虚拟内存,在实际使用的时候才会划分物理空间
- 分配1G能分配成功,申请内存数量应该小于剩余内存(memory+swap)
- 申请的内存如果没有释放会怎么样?
- 在程序退出时,内存依旧会被回收
5. exec进程替换
- linux系统交互都是一个fork和一个exec
- execl(const char *path, const char arg, … / (char *) NULL */);
1 | int main(int argc, char *argv[], char *envp[]) |
6. 信号
- 信号是系统响应某个条件而产生的事件,进程接收到信号会执行相应的操作
- 通过signal()设置相应的响应方式,可以设置以下几种响应方式
- 默认SIG_DEF
- 忽略SIG_IGN
- 自定义 void fun_sig(int sig)
7. 实现自己的KILL命令
- kill 默认信号量是15
- 9号信号是不允许忽略的终止信号
- sscanf解析转化字符串
1 |
|
1 | int main(int argc, char *argv[]) |
8. 有名管道和无名管道
- 进程间通信方式:
- 管道,半双工
- 有名管道
- 无名管道
- 信号量
- 共享内存
- 消息队列
- 套接字
- 管道,半双工
- 有/无名管道区别:
- 有名管道在任意两个进程间通信
- 无名管道在父子进程间通信
- 有名管道创建使用
1 | chengs@ubuntu:~/test$ mkfifo fifo |
- 管道只有O_RDONLY、O_WRONLY两种模式
- 管道文件只能两个进程同时打开,单个进程打开管道会阻塞
1 | //write |
- 无名管道创建使用
1 | int main() |
9.信号量
信号量值代表允许访问的资源数目
- P 操作
- V 操作
- 临界资源:同一时刻,只允许被一个进程或线程访问的资源
- 临界区:访问临界资源的代码段
- ipcs/ipcrm命令查看和删除消息进程通信方式(消息队列、共享内存、信号量)
1 | //函数 |
10.共享内存
- 共享内存是先在物理内存上申请一块空间,多个进程可以将其映射到自己的虚拟地址空间中
- 并未提供同步机制,所以我们通常需要用其他的机制来同步对共享内存的访问。
1 | int shmget(key_t key, size_t size, int shmflg); |
11.消息队列
1 | int msgget(key_t key, int msqflg); |
12.线程
- 在操作系统中线程的实现有三种方式
- 内核级线程
- 用户级线程
- 组合级线程
- 进程与线程的区别
- 进程是资源分配的最小单位,线程是 CPU 调度的最小单位
- 进程有自己的独立地址空间,线程共享进程中的地址空间
- 进程的创建消耗资源大,线程的创建相对较小
- 进程的切换开销大,线程的切换开销相对较小
- 线程接口
- pthread不是 Linux 系统默认的库,编译中要加 -lpthread参数
1 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg); |
13.线程同步
- 互斥锁
1 | int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); |
- 信号量
1 | int sem_init(sem_t *sem, int pshared, unsigned int value); |
- 条件变量
- 条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程
1 | int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); |
- 读写锁
1 | int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr); |
14.线程安全
- 对线程同步,保证同一时刻只有一个线程访问临界资源。
- 在多线程中使用线程安全的函数(可重入函数),所谓线程安全的函数指的是:如果一个
函数能被多个线程同时调用且不发生竟态条件,则我们称它是线程安全的。 - char *strtok(char *str, const char *delim)//分割字符串
- strtok就是线程不安全的,该函数内部存放一个指针静态变量,如果多线程同时使用该指针就会导致线程不安全
- 采用strok_r函数是线程安全的
15.线程fork
- 多线程种如果子线程fork,只会复制该子线程,其他子线程不会复制