Linux进程控制(三)
1. 进程间打开文件的继承
1.1. 用fork继承打开的文件
fork以后的子进程自动继承了父进程的打开的文件,继承以后,父进程关闭打开的文件不会对子进程造成影响。
示例:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
char szBuf[32] = {'\0'};
int iFile = open("./a.txt", O_RDONLY);
if(fork() > 0){//parent process
close(iFile);
return 0;
}
//child process
sleep(3); //wait for parent process closing fd
if(read(iFile, szBuf, sizeof(szBuf)-1) < 1){
perror("read fail");
}else{
printf("string:%s\n",szBuf);
}
close(iFile);
return 0;
}
1.2. 守护进程
Daemon运行在后台也称作“后台服务进程”。 它是没有控制终端与之相连的进程。它独立与控制终端、通常周期的执行某种任务。那么为什么守护进程要脱离终端后台运行呢?守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的任何终端信息所打断。那么为什么要引入守护进程呢?由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个终端,这个终端就称为这些进程的控制终端。当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它被执行开始运转,直到整个系统关闭时才退出。几乎所有的服务器程序如Apache和wu-FTP,都用daemon进程的形式实现。很多Linux下常见的命令如inetd和ftpd,末尾的字母d通常就是指daemon。
守护进程的特性:
1> 守护进程最重要的特性是后台运行。
2> 其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录已经文件创建掩码等。这些环境通常是守护进程从父进程那里继承下来的。
3> 守护进程的启动方式
daemon进程的编程规则
l 创建子进程,父进程退出:
调用fork产生一个子进程,同时父进程退出。我们所有后续工作都在子进程中完成。这样做我们可以交出控制台的控制权,并为子进程作为进程组长作准备;由于父进程已经先于子进程退出,会造成子进程没有父进程,变成一个孤儿进程(orphan)。每当系统发现一个孤儿进程,就会自动由1号进程收养它,这样,原先的子进程就会变成1号进程的子进程。代码如下:
pid = fork();
if(pid>0)
exit(0);
l 在子进程中创建新会话:
使用系统函数setsid()。由于创建守护进程的第一步调用了fork函数来创建子进程,再将父进程退出。由于在调用fork函数的时候,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、控制终端并没有改变,因此,还不是真正意义上的独立开来。而调用setsid函数会创建一个新的会话并自任该会话的组长,调用setsid函数有下面3个作用:让进程摆脱原会话的控制,让进程摆脱原进程组的控制,让进程摆脱原控制终端的控制;
进程组:是一个或多个进程的集合。进程组有进程组ID来唯一标识。除了进程号(PID)之外,进程组ID(GID)也是一个进程的必备属性。每个进程都有一个组长进程,其组长进程的进程号等于进程组ID。且该进程组ID不会因为组长进程的退出而受影响。
会话周期:会话期是一个或多个进程组的集合。通常,一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。
控制终端:由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个控制终端。
l 改变当前目录为根目录:
使用fork函数创建的子进程继承了父进程的当前工作目录。由于在进程运行中,当前目录所在的文件是不能卸载的,这对以后的使用会造成很多的不便。利用chdir("/");把当前工作目录切换到根目录。
l 重设文件权限掩码:
umask(0);将文件权限掩码设为0,Deamon创建文件不会有太大麻烦;
l 关闭所有不需要的文件描述符:
新进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远不会被守护进程读写,而它们一直消耗系统资源。另外守护进程已经与所属的终端失去联系,那么从终端输入的字符不可能到达守护进程,守护进程中常规方法(如printf)输出的字符也不可能在终端上显示。所以通常关闭从0到MAXFILE的所有文件描述符。
for(i=0;i<MAXFILE;i++)
close(i);
(注:有时还要处理SIGCHLD信号signal(SIGCHLD, SIG_IGN);防止僵尸进程(zombie))
下面就可以添加任何你要daemon做的事情
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
void Daemon()
{
const int MAXFD=64;
int i=0;
if(fork()!=0) //父进程退出
exit(0);
setsid(); //成为新进程组组长和新会话领导,脱离控制终端
chdir("/"); //设置工作目录为根目录
umask(0); //重设文件访问权限掩码
for(;i<MAXFD;i++) //尽可能关闭所有从父进程继承来的文件
close(i);
}
int main()
{
Daemon(); //成为守护进程
while(1){
sleep(1);
}
return 0;
}
Example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/stat.h>
#include <time.h>
main()
{
int i = 0;
if(fork() > 0)
exit(0);
setsid();
chdir("/");
umask(0);
for(; i < 64; i++)
{
close(i);
}
i = 0;
while(i < 10)
{
printf("%d\n",i);
time_t ttime;
time(&ttime);
struct tm *pTm = gmtime(&ttime);
syslog(LOG_INFO,"%d %04d:%02d:%02d", i, (1900 + pTm->tm_year), (1 + pTm->tm_mon), (pTm->tm_mday));
i++;
sleep(2);
}
}
通过查看vi /var/log/messages
Linux进程控制(三)的更多相关文章
- Linux进程控制(二)
1. 进程的创建 Linux下有四类创建子进程的函数:system(),fork(),exec*(),popen() 1.1. system函数 原型: #include <stdlib.h&g ...
- Linux进程控制(一)
1. Linux进程概述 进程是一个程序一次执行的过程,它和程序有本质区别.程序是静态的,它是一些保存在磁盘上的指令的有序集合:而进程是一个动态的概念,它是一个运行着的程序,包含了进程的动态创建.调度 ...
- Linux - 进程控制 代码(C)
进程控制 代码(C) 本文地址:http://blog.csdn.net/caroline_wendy 输出进程ID.getpid(). 代码: /*By C.L.Wang * Eclipse CDT ...
- Linux 进程控制
分享知乎上看到的一句话,共勉: 学习周期分为学习,思考,实践,校正四个阶段,周期越短,学习效率越高. 前面讲的都是操作系统如何管理进程,接下来,看看用户如何进行进程控制. 1.进程创建 先介绍一下函数 ...
- linux c编程:进程控制(三)_exec函数
fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...
- Linux进程控制——exec函数族
原文:http://www.cnblogs.com/hnrainll/archive/2011/07/23/2114854.html 1.简介 在Linux中,并不存在exec()函数,exec指的是 ...
- Unix环境高级编程—进程控制(三)
一.解释器文件 解释器文件属于文本文件,起始行形式为: #! pathname[optional-argument] 我们创建一个只有一行的文件如下: #!/home/webber/test/echo ...
- LINUX进程控制
1. 引言 一个程序是存储在文件中的机器指令序列.一般它是由编译器将源代码编译成二进制格式的代码.运行一个程序意味着将这个机器指令序列载入内存然后让处理器(cpu)逐条执行这些指令. 在Unix术语中 ...
- linux进程篇 (三) 进程间的通信2 信号通信
2. 信号通信 用户空间 进程A <----无法通信----> 进程B -----------------|--------------------------------------|- ...
随机推荐
- Excel每隔两行自动求和一次怎么操作?
今天ytkah得到一份数据,要求进行统计分析,由于是原始数据,还没处理过,数据量有点大,如下图所示(Excel每隔两行自动求和),每天的数字由两项组成,男生的人数.消费值和女生的人数和消费值,数字都在 ...
- Java 8怎么了之二:函数和原语
[编者按]本文作者为专注于自然语言处理多年的 Pierre-Yves Saumont,Pierre-Yves 著有30多本主讲 Java 软件开发的书籍,自2008开始供职于 Alcatel-Luce ...
- 游戏引擎网络开发者的 64 做与不做 | Part 1 | 客户端方面
摘要:纵观过去 10 年的游戏领域,单机向网络发展已成为一个非常大的趋势.然而,为游戏添加网络支持的过程中往往存在着大量挑战,这里将为大家揭示游戏引擎网络开发者的 64 个做与不做. [编者按]时下, ...
- Loadrunner监控Centos
一.安装必要包 yum istall gcc gcc-c++ rpcbind -y 二.下载安装必要软件rstatd 下载并安装rstatd,下载地址:http://sourceforge.net/p ...
- JSP 页面打印
<HTML><HEAD><TITLE>javascript打印-打印页面设置-打印预览代码</TITLE> <META http-equiv=Co ...
- 《JavaScript基础教程(第8版)》PDF
简介:JavaScript基础教程(第8版)循序渐进地讲述了JavaScript及相关的CSS.DOM.Ajax.jQuery等技术.书中从JavaScript语言基础开始,分别讨论了图像.框架.浏览 ...
- SSH 端口转发
第一部分 概述 当你在咖啡馆享受免费 WiFi 的时候,有没有想到可能有人正在窃取你的密码及隐私信息?当你发现实验室的防火墙阻止了你的网络应用端口,是不是有苦难言?来看看 SSH 的端口转发功能能给我 ...
- 【hdu1573-X问题】拓展欧几里得-同余方程组
http://acm.hdu.edu.cn/showproblem.php?pid=1573 求小于等于N的正整数中有多少个X满足: X mod a0 = b0 X mod a1 = b1 …… X ...
- OSVERSIONINFO的用法及实例
OSVERSIONINFO 快速信息 Windows NT 支持 Windows 95 支持 Win32s 支持 引入程序库 - 头文件 win ...
- Android核心分析之二十Android应用程序框架之无边界设计意图
Android应用程序框架1 无边界设计理念 Android的应用框架的外特性空间的描述在SDK文档(http://androidappdocs.appspot.com/guide/topics/fu ...