启动新进程的方式
1.system
system 并不是启动新进程的最佳选择。使用他启动新进程,依赖于shell和环境变量。
实验
1 |
|
输出:
1 | PID TTY STAT TIME COMMAND |
将system("ps ax");
替换成system("ps ax &")
;
运行结果为:
1 | Start Run px: |
2.exec 替换进程印象
exec系列函数是由一组相关的函数组成,只是在启动方式和参数上不一致。
分为两大类:
- execl 参数个数不定,最后一个以空指针结束。
- execv 参数以数组形式提供。
以p结尾的函数,表示在PATH这个环境变量下找新的进程。
实验
1 | #include <stdlib.h> |
输出:
1 | PID TTY STAT TIME COMMAND |
进程中没有原来的进程,而且输出结果中原来的输出也没有。
3.fork 复制进程映像
fork调用后,用同样的代码,创建一个子进程,子进程中fork调用返回0,父进程可以通过这点来判断谁是父,谁是子。
父子之间的变量是相互独立的。
实验
1 | #include <sys/types.h> |
输出:
1 | ========start========= |
如果加上wait,父进程等待子进程退出。
1 | ... |
输出:
1 | ========start========= |
可以看到父进程的log输出在子进程后面。
僵尸进程
fork 处理来的子进程比父进程先结束,但是由于需要等待父进程,所以还在在进程表中。
这种情况他就是一个僵尸进程。
如果父进程异常终止,则子进程会挂到init进程中,永远没有机会释放。
wait是父进程等待挂起。waitpid不会挂起父进程,可以通过周期性的查询知道子进程的状态。
启动线程的方法:
int pthread_create(&threadid,NULL,thread_function,(void*)message);
第二个参数是线程的属性,一般情况设置为NULL,第3个参数是线程函数。
int pthread_join(threadid,&threadresult);
等待线程的结束,并取得返回退出的结果。退出的结果存在threadresult
pthread_exit(“end thread”);
结束线程,并返回结果。
1 |
|
编译方法:
1 | gcc ./thread.c -o thread -lpthread |
运行结果:
1 | create thread |
线程同步
信号量
信号量线程同步包括二进制信号量和计数信号量。
pshared是一直为0pshared
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_destroy(sem_t *sem);