Linux学习:系统编程之进程基本概念

什么是程序?什么是进程?区别在哪里?
程序是通过gcc xx.c-o pro,在磁盘中生产的pro文件
进程是程序正在运行
如何查看系统中的程序:使用ps+grep配合使用查看某一个进程

进程标识符
每一个进程都有一个非负整数表示的唯一的ID------pid
pid=0:称为交换进程
pid=1:init进程——系统初始化

我们可以通过getpid函数获取自身的进程标识符,getppid获取父进程的进程标识符

父进程、子进程
由进程A创建了进程B,A叫做父进程,B叫做子进程,简单理解为我们与父亲之间的关系
在这里插入图片描述
我们可以通过fork函数创建一个进程,fork成功调用,返回两次
返回值:0,代表当前进程为子进程
返回值:非负数,代表当前进程为父进程
返回值:-1,代表调用失败

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

int main(){
	pid_t pid;
	pid=fork();
	if(pid>0){
		printf("this is father,pid=%d\n",getpid());
	}else if(pid==0){
		printf("this is child,pid=%d",getpid());
	}
	return 0;
}

fork创建一个子进程的目的:
1、一个父进程希望可以多一个同样的自己来同时执行不同的代码。最常见的就是父进程等待客户端的服务请求,当请求到达时,父进程调用fork,让子进程来处理这个请求,父进程继续等待下一个请求
2、一个进程要执行一个不同的程序,这边我们常常调用exec函数

创建进程也可以用vfork函数来创建,那它跟fork函数的区别在于:
1、vfork直接使用父进程的存储空间,不拷贝
2、vfork保证子进程先运行,当子进程调用exit退出后,父进程再执行

进程退出

正常退出

  1. main函数调用return
  2. 进程调用exit(),标准c库语言
  3. 进程调用_exit()或者_Exit,属于系统调用(补充:进程最后一个线程返回,最后一个线程调用pthread_exit())

异常退出

  1. 调用abort
  2. 当进程收到某些信号,如ctrl+c
  3. 最后一个线程对取消(cancellation)请求作出响应

如果我们想要实现终止进程能够通知其父进程它是如何终止,可以通过三个终止函数(exit、_exit、_Exit)将其退出状态作为参数传送给函数,那么禁止进程的父进程用wait或者waitpid函数取得终止状态

在这里插入图片描述
在这里插入图片描述

父进程等待子进程退出,并收集子进程的退出状态,如果子进程退出状态不被收集,会成为僵尸进程
在这里插入图片描述
函数作用:如果所有所有子进程都还在运行,则阻塞;如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回;如果没有任何子进程,则立即出错返回

status参数:是一个整数型指针,非空:子进程退出状态放在它所指向的地址中;空:不关心退出状态
pid参数:

  • pid== -1,代表着等待任何一子进程,
  • pid>0,代表等待其进程ID与pid相等的子进程
  • pid==0,代表其组ID等于调用进程组ID的任何一子进程
  • pid<-1,代表着其组ID等于pid绝对值的任一进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(){
    pid_t pid;
    int cnt;
    int status=10;
    pid=fork();
    if(pid>0)
    {   
        wait(&status);//接收子进程的退出状态
        printf("child quit child status=%d\n",WEXITSTATUS(status));
        while(1){
        printf("this is father print,pid=%d\n",getpid());
        printf("cnt=%d\n",cnt);
        sleep(1);
        }
    }else if(pid==0){
        while(1){
            printf("this is child print,child pid=%d\n",getpid());
            sleep(2);
            cnt++;
            if(cnt==5){ //当子进程运行5次后,退出
                exit(3);

            }
        }
    }
    return 0;
}

exec族函数

功能:在调用进程内部执行一个可执行文件。
在这里插入图片描述
函数参数说明:
path:可执行文件的路径名称
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则为路径名,没有就按环境变量,在所指定的目录下搜素可执行文件

举例:通过exel和fork实现文件的拷贝

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

int main() {
    pid_t pid;
    int data;

    while (1) {

        printf("input a number:\n");
        scanf("%d", &data);
        if (data == 1) {
            pid = fork();
            if (pid > 0) {
                wait(NULL);

            } else if (pid == 0) {
                if(execl("./copy","copy","file","file2",NULL)== -1){  //子进程调用cp.c
                    perror("run failed");
                }
                printf("copy successfully\n");
                exit(0);
            }

        } else {
            printf("wait\n");
        }
    }

    return 0;
}
//cp.c-文件拷贝
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **agrv) {
    int fd;
    int fd2;
    int n_read;
    int n_write;
    int size;
    char *buf;
    if(argc!=3){
        printf("参数个数不对\n");
        exit(-1);

           }
    fd = open(agrv[1], O_RDWR);
    if (fd == -1) {
        perror("open file fail");
        fd = open(agrv[1], O_RDWR | O_CREAT | O_TRUNC, 0600);
        if (fd == -1) {
            perror("creat file fail");
            exit(-1);
        }
    }
    size = lseek(fd, 0, SEEK_END);
    buf = (char *)malloc(size);
    printf("%d\n", size);
    lseek(fd, 0, SEEK_SET);
    n_read = read(fd, buf, size);
    printf("read %d from file content:%s\n", n_read, buf);

    close(fd);
    fd2 = open(agrv[2], O_RDWR);
    if (fd2 == -1) {
        perror("file2 open file");
        fd2 = open(agrv[2], O_RDWR | O_CREAT | O_TRUNC, 0600);
        if (fd2 == -1) {
            perror("creat file2 fail");
            exit(-1);
        }
    }
    n_write = write(fd2, buf, size);
    memset(buf, '\0', size);
    printf("write %d to file2\n", n_write);
    close(fd2);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值