进程和信号
由于在公司主要是嵌入式操作系统方面的内容,所以linux应用开发和内核源码分析也是我接下来重点研究的一个方向,目前的计划是:
书籍方面:linux程序设计,Linux高级程序设计,Linux内核
课程:哈工大操作系统课程,MIT 6.828等
代码:希望在xv6基础上进行开发
目标是为了研究操作系统,比如xv6、linux等系统的源码,但是首先要熟悉这些系统接口。
进程和信号这一篇主要根据linux程序设计这本书第11章内容为基础,这本书对新手非常友好,推荐学习linux的入门同学进行阅读。
什么是进程
UNIX标准把进程定义为:“一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源”。在《linux内核设计与实现》这本书中的定义为:”进程就是处于执行期的程序“
对于我自己的理解来说,我们可以写一个main函数,然后编译进行运行,但此时我们需要运行其它程序时该怎么办?此时就需要进行进程切换,调用fork()函数执行新的程序,使用exec()函数创建新的地址空间。
Linux系统启动时将运行一个init进程,是系统运行的第一个进程,进程号为1.
使用system函数启动新进程
system函数的作用是运行以字符串参数的形式传递给它的命令并等待命令的完成。
//首先写一个helloworld程序
//在任意一个linux文件夹下面,可以命名为helloworld.c
//想要运行的话:
//第一步:gcc helloworld.c -o helloworld
//第二步:./helloworld
#include <stdio.h>
int main()
{
printf("hello world/n");
return 0;
}
//再编写system1.c函数,调用system()函数,进而调用helloworld
#include <stdlib.h>
#include <stdio.h>
int main()
{
system("./helloworld");
exit(0);
}
但其实我们平时用的是fork()函数创建新的进程,为什么那?虽然system()函数听起来更酷一点,但是启动system()函数需要首先启动一个shell,所以效率并不是很高。
fork(), exec(),wait()
首先是exec()系列函数:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("running ps with execlp\n");
execlp("ps","ps","ax",0);
printf("Done\n");
exit(0);
}
//与system()函数区别就是新的程序启动后,原来的程序不再运行,
//最下面的printf()函数不会执行
fork()函数复制当前的进程,但新进程有自己的数据空间,环境和文件描述符。
调用fork()示例:
//fork1.c
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
char * message;
int n;
pid = fork();
switch(pid)
{
case -1: //this is error
perror("fork failed");
exit(1);
case 0:
message = "this is the child"; //child
n = 5;
break;
default:
message = "this is the parent"; //parent
n = 3;
break;
}
for(;n>0;n--){
puts(message);
sleep(1);
}
exit(0);
}
重点:fork()和exec()函数结合在一起使用就是创建新进程所需要的一切了。
wait系统调用将暂停父进程直到它的子进程结束为止,调用返回子进程的PID。
信号
信号是UNIX和Linux系统响应某些条件而产生的一个事件。在键盘上敲入中断字符(通常是Ctrl+C组合键)就会向当前正在运行的程序发送SIGINT信号,这将引起程序终止,除非事先安排捕获这个信号。
//程序运行时按下ctrl+c,调用signal()函数,进而调用ouch()函数
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! -I got signal %d\n",sig);
(void)signal(SIGINT,SIG_DFL);
}
int main()
{
(void)signal(SIGINT,ouch);
while(1){
printf("HEllo world\n");
sleep(1);
}
}
alarm函数
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static int alarm_fired = 0;
void ding(int sig)
{
alarm_fired = 1;
}
int main()
{
pid_t pid;
printf("alarm application starting\n");
pid = fork();
switch(pid){
case -1:
perror("fork failed");
exit(1);
case 0:
sleep(5);
kill(getppid(),SIGALRM); //注意是getppid()
exit(0); //子进程执行到这里
}
printf("waiting for alarm to fo off\n");
(void)signal(SIGALRM,ding);
pause();
if(alarm_fired)
printf("Ding!\n");
printf("done\n");
exit(0);
}
进程和线程内容太丰富了,估计要有很多篇来描写,下一篇是线程概述。