守护进程的特点:
1.守护进程是Linux中三大进程之一,始终运行在后台,通常系统开启时运行,系统关闭时结束。
2.独立于控制终端(与终端无关)。
3.周期性执行某种任务或等待某些发生的事件。
创建守护进程:(每隔5秒将系统时间写入到文件)
1.创建子进程,父进程退出 (子进程成为后台进程)
2.设置新的会话
3.置工作目录
4.重设文件掩码
5.关闭从父进程继承下来的文件描述符
6.周期性执行任务
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
//1.创建子进程,父进程退出
if(fork()>0)
{
exit(0);
}
//2.设置新会话
if(setsid()<0)
{
perror("setsid error!");
return -1;
}
//3.设置工作目录
chdir("/tmp");
//4.修改文件掩码
umask(0);
//5.关闭父进程继承下来的文件描述符
int i=0;
for(i=0;i<getdtablesize();i++)
{
close(i);
}
while(1)
{
system("echo `date` >> daemon.txt");
sleep(5);
}
return 0;
}
传统的unix通信方式
无名管道
1.只能用于具有亲缘关系(父子进程/兄弟进程)的进程之间的通信,速度慢,容量有限
2.半双工的通信方式,具有固定的读端fd[0]和写端fd[1].
3.管道可以看成一种特殊的文件,对于它的读写我们实用文件IO中read和write
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(void)
{
//1.创建一个无名管道
//1-1.定义一个包含两个元素的整形数组
int fd[2]={0};
//1-2.创建无名管道
if(pipe(fd)<0)
{
perror("pipe error");
return -1;
}
//创建成功之后,就有了固定读端(fd[0])和写端(fd[1])
//2.创建子进程
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork error");
return -1;
}
else if(pid==0)
{
//子进程 fd[0]读 fd[1]写
//子进程发送
//1.关闭读端
close(fd[0]);
char buf[20]={'\0'};
//2.发送数据
while(1)
{
fgets(buf,sizeof(buf),stdin);
write(fd[1],buf,strlen(buf));
}
}
else if(pid>0)
{
//父进程 fd[0]读 fd[1]写
//1.关闭写端
close(fd[1]);
char buf[20]={'\0'};
//2.发送数据
while(1)
{
//1.从无名管道读取到buf
read(fd[0],buf,sizeof(buf));
//2.从buf显示中标准输出
printf("顶针:%s",buf);
}
}
}
写无名管道,读端必须存在,否则会异常退出,管道断裂
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
//1.创建一个无名管道
//1-1.定义一个包含两个元素的整形数组
int fd[2]={0};
//1-2.创建无名管道
if(pipe(fd)<0)
{
perror("pipe error");
return -1;
}
close(fd[0]);//关闭读端
//创建成功之后,就有了固定读端(fd[0])和写端(fd[1])
//2.创建子进程
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork error");
return -1;
}else if(pid==0)
{
//子进程 fd[0]读端 fd[1]写端
//子进程发送:写管道
// 1.关闭读端
close(fd[0]);
char buf[20]={'\0'};
// 2.发送数据
while(1)
{
fgets(buf,sizeof(buf),stdin); //1.将数据从键盘输入
if(strncmp(buf,"exit",4)==0) break;
write(fd[1],buf,strlen(buf)); //2.将数据写入到无名管道中
}
exit(0);//子进程退出
}else if(pid>0)
{
//父进程 fd[0]读端 fd[1]写端
// 1.关闭写端
close(fd[1]);
char buf[20]={'\0'};
// 2.读取数据
while(1)
{
//父进程回收子进程的资源
int status=0;
int id=waitpid(-1,&status,WNOHANG);//非阻塞等待子进程结束
if(id>0) //id>0表示子进程退出
{
if(WIFEXITED(status))
{
printf("正常结束的值:%d\n",WEXITSTATUS(status));
}else if(WIFSIGNALED(status))
{
printf("信号的值为:%d\n",WTERMSIG(status));
}
break;//子进程结束之后,父进程一起结束
}
//1.从无名管道读取到buf
read(fd[0],buf,sizeof(buf));
//2.从buf显示中标准输出
printf("%s",buf);
}
}
}