进程和信号

本文详细介绍了Linux环境下的进程概念,包括进程的定义和创建,如通过fork()和exec()函数。还探讨了系统调用wait()的作用以及信号(Signal)机制,如响应中断字符SIGINT的处理。文中通过示例代码解释了如何使用这些函数和机制,并指出在实际编程中选择fork()而非system()的原因。最后提到了alarm()函数和信号的结合使用。文章为理解操作系统内核和进程管理打下基础。
摘要由CSDN通过智能技术生成

进程和信号

由于在公司主要是嵌入式操作系统方面的内容,所以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);
}

进程和线程内容太丰富了,估计要有很多篇来描写,下一篇是线程概述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值