终端、进程组、守护进程

 1.   终端 、进程组

1. 什么终端 (tty就是) :所有输入、输出设别的总称  ,
 输入, 键盘、鼠标 、摄像头 、麦克风
 输出:屏幕、音响、打印机

 字符终端 : ctrl+alt +f1 -  f6
 图形终端: alt + f7
 网络终端: xshell


 虚拟终端 (pty就是) : 虚拟机小窗口  xshell , 可以输入、输出

2.   线路规程:
        xshell 原理    ssh客户端--  ssh服务器 - 伪终端bash

3.   进程组:
       父进程fork进程以后, 父进程就是组长, 父进程id 就是进程组id

如何把创建的子进程分配到其他进程组中   ?? 可以的

  ps aux|grep bash  所有的虚拟终端


  操作函数:
  getpgrp(void):  获取当前进程的进程组
  getpgid(pid_t pid):   获取指定进程的进程组ID

  setpgid(pid_d pid,pid_t pgid):   把pid 加入 pgid进程组

  子进程 可以加入 bash 组
  setpgid(pid_d pid,pid_d pid) 独立一个组,自己pid为组
  父进程可以改变子进程
  非root用户进程只能改变自己创建的子进程,或有权限操作的进程

代码功能: 在父进程中 自立门户,把自己加入自己的进程组, 把父进程加入bash组

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <signal.h>


int main() {
 int i;
 pid_t  pid=fork();

 if(pid < 0){
  perror("fork fail");
  exit(1);
 }else if(pid == 0){
printf("child pid ==%d\n", getpid() );
printf("chidl group=%d\n", getpgid(0));  // 返回组id 
printf("child getppid=%d\n",getppid());
// printf("child group=%d\n", getpgrp()); 
sleep(7);  //子进程睡7s ,等待父进程操作  , 父进程把子进程自立门户
printf("change chidl group=%d\n", getpgid(0));  // 返回组id 
 }else if(pid>0){
    sleep(1);  //给子进程打印内容
    setpgid(pid,pid);  // 父进程把自己加入 自己组.,  子进程自立门户,成为进程组长, 
    sleep(13); 

    printf("\n");
    printf("parent id=%d\n", getpid());
    printf("bash --  parent group id=%d\n",getppid());  // bash id 
    printf("parent group id =%d\n", getpgid(0)); // 自己的进程组ID

    sleep(5);   
    // 符进程给进程设置上面, 父进程把自己加入bash组, bash不是root 
    setpgid(getpid(),getppid());
    printf("groupid of parent ischange to= %d\n",getpgid(0));

    while(1){  }
 
 }

  return 0;
}

执行输出:

 2.  守护进程

  4.1. 如何创建回话

 如何创建回话:
    1. 创建会话进程不能是进程组组长,[比如父进程],该进程[子进程]成为新会话的首进程
    2. 新会话丢弃原有控制终端,该会话没有控制终端[这种程序不能和用户进程操作,适合在后台运行,守护进程]
    3. 建立新会话,调用fork,父进程终止,子进程调用setisid()
    4. 建立成功以后   pid=gid=sid
    5. 建立会话需要root权限 [ubuntu不需要]
    ppid pid gid sid

/**
 * 如何创建回话:
    1. 创建会话进程不能是进程组组长,[比如父进程],该进程[子进程]成为新会话的首进程
	2. 新会话丢弃原有控制终端,该会话没有控制终端[这种程序不能和用户进程操作,适合在后台运行,守护进程]
	3. 建立新会话,调用fork,父进程终止,子进程调用setisid()
	4. 建立成功以后   pid=gid=sid
	5. 建立会话需要root权限 [ubuntu不需要]
    ppid pid gid sid
 */
int main00011() {

	pid_t pid = fork();

	if (pid < 0) {
		perror("fork fail");
		exit(-1);
	} else if (pid == 0) {
		printf("child process PID is %d\n", getpid());
		printf("group id is %d\n", getpgid(0));
		printf("session is %d\n", getsid(0));

		sleep(10);
		setsid();  // 创建会话
		printf("change.......");
		printf("child process PID is %d\n", getpid());
		printf("group id is %d\n", getpgid(0));
		printf("session is %d\n", getsid(0));

	} else {
		// 父进程死了
	}

	return 0;
}

 4.2.守护进程创建:
  1. 独立于控制终端[运行在操作系统后台]并且周期执行某种任务
  2. 不受用户登录注销影响,通常以d结尾方式   比如vsftpd[d]

用户程序退出,注销不影响

比如:vsftpd :     启动,等待客户端连接    httpd 、 sshd   xinted  , mysql就是守护进程自动启动的

比如在./bashrc  启动程序

int main0000013() {
	pid_t pid = fork();

	if(pid>0){
		exit(0);  // 父进程终止
	}

	__pid_t spid=setsid();  //创建新会话
     if(spid == -1){
    	 perror("setsid fail");
    	 exit(-1);
     }

     __pid_t cpid= chdir("/home/denganzhi/linux");
     // 改变工作目录
     //  why? 如果程序在U盘上运行,那么拔掉U盘,程序会崩溃
     if(cpid ==-1){
    	 perror("chdir fail");
    	 exit(-1);
     }

     umask(0022);  //改变文件访问权限掩码,避免fork 之前进程修改umask权限,避免跟着原来的掩码走

//0 1 2 进程启动,自动打开, 回话脱离控制终端,0 1 2  无效了
// 
    close(STDIN_FILENO);  // 关闭0号文件描述符, 后面的open 就占据了 0号描述符 

     // 继承打开文件不会用到,浪费系统资源
     // 如果直接关闭,那么文件描述从0开始,不符合习惯
     // 可以定向到一个文件,那么还是从3开始文件描述符
    int fd=open("/dev/null",O_RDWR);
    if(fd == -1){
    	perror("open error");
    	exit(-1);
    }
    dup2(fd,STDOUT_FILENO);
    dup2(fd,STDERR_FILENO);

    while(1){

    }

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值