linux进程

进程

1.进程标识符PID

类型 pid_t;命令ps;进程号是顺次向下使用;getpid();getppid();

  • ps axf 查看进程树
  • ps axm
  • ps ax -L
  • ps -ef

2.进程的产生

  • fork()
    - 注意理解关键字: duplicating,意味着拷贝 克隆 一模一样等含义; - fork 后父子进程的区别 : fork 的返回值不一样, pid不同 ,ppid也不同, 未决信号与文件锁不继承,资源利用量清0; - init进程:1号, 是所以进程的祖先进程 pid == 1;调度器的调度策略来决定哪个进程先运行;fflush()的重要性。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    printf("%d start !\n",getpid());
    fflush(NULL);//记得刷新 否则begin放到缓冲区 父子进程fork复制的缓冲区里各有一句begin

    pid_t pid = fork();

    if (pid == 0){
        printf("child %d\n",getpid());
    }else{
        printf("parent %d\n",getpid());
    }
    getchar();
    printf("pid %d end\n",getpid());
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#define LEFT 2
#define RIGHT 200

int main()
{
    pid_t pid = 0;
    int i,j,mark;

    for (i = LEFT;i <= RIGHT;i++){
        pid = fork();
        if (pid == 0){
            mark = 1;
            for (j = 2;j < i/2;j++){
                if (i%j == 0){
                    mark = 0;
                    break;
                }
            }
            if (mark) {
                printf("%d is a primer\n",i);
            }
            exit(0);//记得结束子进程
        }
    }
    getchar();

    exit(0);
}
//孤儿进程和僵尸进程
//读时共享,写时复制
  • vfork()

3.进程的消亡以及释放资源

  • wait();
  • waitpid();
  • waitid();
  • wait3();
  • wait4();
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>

#define N 3
#define LEFT 100000002
#define RIGHT 100000200
//分块;交叉分配;进程池
//交叉算法计算 池类算法涉及到竞争
int main()
{
    printf("[%d] start !\n",getpid());
    fflush(NULL);//记得刷新 否则begin放到缓冲区 父子进程的缓冲区里各有一句begin
    pid_t pid = 0;
    int i,j,mark;

    for (int n = 0;n < N;n++){
        pid = fork();
        if (pid < 0){
            perror("fork");
            for (int k = 0;k < n;k++){
                wait(NULL);
            }
            exit(1);
        }

        if (pid == 0){
            for (i = LEFT+n;i <= RIGHT;i+=N){
                mark = 1;
                for (j = 2;j <= i/2;j++){
                    if (i%j == 0){
                        mark = 0;
                        break;
                    }
                }
                if (mark) {
                    printf("%d is a primer\n",i);
                }
            }
            printf("[%d] exit\n",n);
            exit(0);
        }

    }

    int st,n;
    for (n =0 ;n < N;n++){
        //wait(NULL);
        wait(&st);
        printf("%d end\n",st);
    }

    exit(0);
}

//bash:bourne shell

exec函数族

exec 替换 当前进程映像

  • extern char **environ
  • execl();
  • execlp();
  • execle();
  • execv();
  • execvpa();
  • 注意刷新fflush流;

进程调用一种 exec 函数时,该进程完全由新程序替换,而新程序则从其 main 函数开始执行。因为调用 exec 并不创建新进程,所以前后的进程 ID (当然还有父进程号、进程组号、当前工作目录……)并未改变。exec 只是用另一个新程序替换了当前进程的正文、数据、堆和栈段(进程替换)。

进程间通信:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

include <stdio.h>
#include <unistd.h>
 
int main(int argc, char *argv[])
{
 printf("before exec\n\n");
 
 /* /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)
	   ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意
	   -a,-l,-h:给外部程序 ls 传的参数
	   NULL:这个必须写上,代表给外部程序 ls 传参结束
	*/
	execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);
 
 // 如果 execl() 执行成功,下面执行不到,因为当前进程已经被执行的 ls 替换了
	perror("execl");
 printf("after exec\n\n");
 
 return 0;
}
一个小shell
//lhq yyds
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <glob.h>
#include <string.h>

#define BUFSIZE 1024
#define DELIMS " \t\n"

extern char **environ;

static int cd(char *path){
    int ret = chdir(path);
    if (ret == -1){
        perror("chdir");
    }
    return ret;
}

static void readrc(char *name){
    FILE *fp;
    fp = fopen(name,"r+");
    //处理文件内容
    fclose(fp);
}

static void prompt()
{
    char pwd[BUFSIZE];
    char name[BUFSIZE];
    getcwd(pwd,BUFSIZE);
    getlogin_r(name,BUFSIZE);
    printf("%s %s $ ",name,pwd);
}

static int parse(char *linebuf,glob_t *globres){
    char *tok;
    int flag = 0;
    

    while (1){
        tok = strsep(&linebuf,DELIMS);
        if (tok == NULL){
            break;
            return -1;
        }else if(strcmp(tok,"cd") == 0){
            char *path = strsep(&linebuf,DELIMS);
            return cd(path);
        }else if(tok[0] == '\0'){
            continue;
        }

        glob(tok,GLOB_NOCHECK|GLOB_APPEND*flag,NULL,globres);//第一次不能append glob_argv中是随机值 GLOB_NOCHECK | (GLOB_APPEND*flag)==0 第一次不append
        flag = 1;
    }
    return 1;
}


//之后记得 将 ctrl+c 转为 stdout:\n 将ctrl+d 转为 退出+再见标语
int main()
{
    printf("This is YSHELL\n");

    pid_t pid;
    char *linebuf = NULL;
    size_t lienbuf_size = 0;
    glob_t globres;//解析命令行

    //读取配置文件
    char *yshrc = "/home/yixingwei/.yshrc";//填一个绝对路径
    readrc(yshrc);

    while(1){
        prompt();


        //获取命令
        getline(&linebuf,&lienbuf_size,stdin);
        //解析命令
        int ret = parse(linebuf,&globres);
        
        if (ret == -1){
            
        }else if (ret == 0){//内部命令
            
        }else if (ret == 1){//外部命令
            fflush(NULL);
            pid = fork();
            if (pid < 0){
                perror("fork()");
                exit(1);
            }else if(pid == 0){
                execvp(globres.gl_pathv[0],globres.gl_pathv);
                perror("execl()");
                exit(1);
            }
        }
        waitpid(pid,NULL,0);
    } 
    
    exit(0);
}

用户权限以及组权限

  • u+s 当其他用户调用该可执行文件时,会切换成当前可执行文件的user的身份来执行

  • g+s

  • uid/gid

    • r real
    • e effective

函数

  • getuid() 返回 real
  • geteuid() 返回 effective
// mysudo
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>

int main(int argc,char **argv)
{
    if (argc < 3){
        fprintf(stderr,"Useage");
        exit(1);
    }

    pid_t pid;

    pid = fork();
    if (pid == 0){
        setuid(atoi(argv[1]));
        execvp(argv[2],argv+2);
        perror("execvp()");
        exit(1);

    }else {
        wait(NULL);
    }

    exit(0);
}

$ su
# chown root ./mysudo
# chmod u+s ./mysudo

//Linux chown(英文全拼:change owner)命令用于设置文件所有者和文件关联组的命令。利用 chown 将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户 ID,组可以是组名或者组 ID,文件是以空格分开的要改变权限的文件列表,支持通配符。 。
$ ./mysudo 0 /etc/shadow
  • getgid
  • getegid
  • setuid 设置effective
  • setgid 设置effective
  • setreuid 交换 r e //是原子的交换
  • setregid 交换 r e

解释器文件

system()

可以理解成 fork+exec+wait 封装

进程会计

  • acct()

进程时间

  • times()

守护进程

  • 会话 sesion 标识是sid
  • 终端
  • setsid()
  • getpgrp()
  • getpgid()
  • setpgid()
  • 单实例守护进程:锁文件/var/run/name.pid
  • 启动脚本文件:/etc/rc*…

系统日志

  • syslogd 服务
  • openlog
  • syslog
  • closelog
#include <stdio.h>
#include <stdlib.h>
#include <sys/syslog.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>

#define FNAME "/tmp/out"

static int deamonize(){
    int fd;
    pid_t pid;
    pid = fork();

    if (pid < 0){
        return -1;
    }

    if (pid > 0){
        exit(0);
    }

    fd = open("/dev/null",O_RDWR);//输出都忽略
    if (fd < 0){
        return -1;
    }
    if (pid == 0){
        printf("test");
        fflush(NULL);
        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);
        if (fd > 2){
            close(fd);
        }
        setsid();//脱离终端
        //umask();
        chdir("/");
    }
    return 0;
}

int main()
{
    FILE* fp;

    //开启日志服务
    openlog("print i",LOG_PID,LOG_DAEMON);

    if (deamonize()){
        syslog(LOG_ERR,"init failed!");
    }else{
        syslog(LOG_INFO,"successded!");
    }

    fp = fopen(FNAME,"w+");
    if (fp == NULL){
        syslog(LOG_ERR,"write file failed!");
        exit(1);
    }

    syslog(LOG_INFO,"%s opened",FNAME);

    for(int i = 0; ;i++){
        fprintf(fp,"%d\n",i);
        fflush(NULL);
        syslog(LOG_DEBUG,"%d 写入",i);
        sleep(1);
    }

    closelog();
    fclose(fp);
    exit(0);
}

 journalctl _PID=XXX


syslog(LOG_INFO,“successded!”);
}

fp = fopen(FNAME,"w+");
if (fp == NULL){
    syslog(LOG_ERR,"write file failed!");
    exit(1);
}

syslog(LOG_INFO,"%s opened",FNAME);

for(int i = 0; ;i++){
    fprintf(fp,"%d\n",i);
    fflush(NULL);
    syslog(LOG_DEBUG,"%d 写入",i);
    sleep(1);
}

closelog();
fclose(fp);
exit(0);

}


~~~ bash
 journalctl _PID=XXX

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值