linux系统编程--进程函数

1进程控制

1.1fork{int fork(void)}

在这里插入图片描述

1.1.1 返回值

返回值 含义
-1 失败
0 子进程逻辑控制流
其他(子进程PID) 父进程逻辑控制流

1.1.2特点

1: 调用一次,返回两次
2:相同但是独立的地址空间
3: 并发执行

int main(int argc,char *argv[]){
	int n=atoi(argv[1]);
	int i;
	for(i=0;i<n;i++){
		int pid=fork();
		if(pid==0){
			printf("%d PID:%d\n",i,getpid());
		exit(0);
		}else{
			printf("%d create %d\n",i,pid);
		}

	}


}

4: 共享文件

#include <stdio.h>
#include <unistd.h>
int i = 100;
int main(){
    int j=100;
    FILE* fd = fopen("./test","w+");
    pid_t pid = fork();
    if(pid == 0){// child
        int k;
        for(k=0;k<10000;k++)
            fprintf(fd,"this is childi%d\t j%d\n",++i,++j);
    }else{
        int k;
        for(k=0;k<10000;k++)
            fprintf(fd,"this is fatheri%d\t j%d\n",--i,--j);
    }
}

1.1.3问题

1:子进程创建成功后 代码的执行位置?
父进程执行到那,子进程就从那开始执行
2:父子进程执行的顺序?
并发执行 谁抢到cpu谁执行

1.2getpid getppid

函数 接口
pid_t getpid() 获取当前进程ID
pid_t getppid() 获取当前进程父进程ID

查看进程的PID和PPID

ps -o pid,ppid,cmd,s

1.3创建多进程

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<mqueue.h>
#include<sys/mman.h>
#include<string.h>
#include<pthread.h>
#include<sys/syscall.h>
#include<sys/prctl.h>
#include<signal.h>
#include<sys/wait.h>
#include<sys/types.h>
void handle(int sig){
	printf("%d exit\n",wait(3));

}
int main(int argc,char *argv[]){
	signal(SIGCHLD,handle);
	int n=atoi(argv[1]);
	int i;
	for(i=0;i<n;i++){
		int pid=fork();
		if(pid==0){
			printf("%d PID:%d\n",i,getpid());
			break//防止有孙子进程 只要是子进程都跳出
		}else{
			printf("%d create %d\n",i,pid);
		}

	}


}

#2

2进程之间数据共享

2.1特点

在这里插入图片描述

2.2全局变量

父子进程之间不能使用全局变量通信 因为两个进程间内存不能共享
在这里插入图片描述

3exec函数族

在这里插入图片描述

3.1作用:

	1:让父子进程执行不相干的操作
	2:能够替换进程地址空间段的源代码.text段
	3:当前程序中调用另外一个程序
	4:PID不变

3.2 分类

分类 函数
字符串数组参数 execv()、execvp()、execve()
可变参数 execle()、execlp()、execl()

3.3exec函数组名字规律

字符 含义
v 第二个参数是数组
l 第二个参数之后是变参
p 第一个参数是文件名
e 最后一个参数是环境变量

3.4返回值

返回值 含义
-1 失败
不返回 成功

3.5实例

3.5.1excel

占位:可以随便写
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
int main(int argc,char *argv[]){
	int i;
	for(i=0;i<8;i++){
		printf(" parent:%d\n",i);
	}
	
	int pid=fork();
	if(pid==0){
		//只是程序使用的子进程的地址覆盖
		execl("/bin/ls","666","-l",NULL);
		
	}
	//所以子进程不执行下面操作
	for(i=0;i<3;i++){
		printf(" --------i:%d\n",i);
	}

return 0;
}

3.5.2excep

不用写命令路径,只需要写命令 系统直接在SPATH环境变量中找
在这里插入图片描述

excel("ps","ps","aux",NULL);

4 系统函数int system(Shell字符串)

4.1返回值

返回值 含义
-1 失败
127 无法启动shell来运行
其他 命令退出码

4.2 特点

一次调用,一次返回

4.3示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(int argc,char** argv){
    printf("PID:%d\n",getpid());    
    system("sleep 3&");
    printf("PID:%d\n",getpid());    
}

4.4本质

shell执行命令/程序

5结束进程

5.1分类

方式 说明
1 main函数退出 只能用在main函数内
2 调用exit()函数 一般用在main函数以外的函数
3 调用_exit()函数 一般用来结束子进程
4 调用abort()函数 一般用来异常退出
5 信号终止 终止其他进程

5.2示例

return退出

#include <stdio.h>
#include <unistd.h>
 
int main(){
    printf("PID:%d,PPID:%d\n",getpid(),getppid());     
    return 100;
}

exit()/abort()退出

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    printf("PID:%d,PPID:%d\n",getpid(),getppid());
    //exit(EXIT_FAILURE);
    abort();
}
作者:jdzhangxin
链接:https://www.jianshu.com/p/011bd63208ef
来源:简书

6休眠进程

int sleep(unsigned int secs)

6.1参数

secs指定休眠的秒数,-1表示永久休眠

6.2返回值

未休眠的秒数

6.3特性

如果没有信号中断,休眠指定秒数返回0,否则马上返回未休眠的秒数。
示例:电子时钟
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <strings.h>
 
int main(){
    int i = 0;
    for(;;){
        time_t t;
        time(&t);
        struct tm* ptm =  gmtime(&t);
        char buf[BUFSIZ];
        bzero(buf,BUFSIZ);
        strftime(buf,BUFSIZ,"%P %T",ptm);
        printf("\r%s",buf);
        fflush(stdout);
        sleep(1);
    }
}
作者:jdzhangxin
链接:https://www.jianshu.com/p/011bd63208ef
来源:简书

暂停int pause()

返回值

总是-1

特性

    如果程序没有处理信号,直接中断,执行默认信号处理,程序后续代码不再执行。
    如果程序存在信号处理,执行信号处理后,执行后续代码。

等待信号

No. 快捷键 信号 说明
1 Ctrl+C SIGINT 中断
2 Ctrl+Z SIGTSTP 终端的停止信号

示例
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void test(int sig){
    printf("revc a signal%d",sig);
}
 
int main(){
    signal(SIGINT,test);
    printf("before pause\n");
    pause();
    printf("after pause\n");
}


作者:jdzhangxin
链接:https://www.jianshu.com/p/011bd63208ef
来源:简书

7回收进程

7.1特殊进程

概念 出现条件 导致结果 是否有害 原因
1 孤儿进程 父进程先于子进程退出 init进程作为新的父进程 无害 进程结束后 能够释放用户区空间释放不了pcb 必须有父进程释放
2 僵尸进程 子进程退出,父进程没有获取子进程的状态信息 调用wait或waitpid 有害,避免出现僵尸进程 父进程没有释放进程的pcb ,孩子就变成了僵尸进程
//孤儿进程
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
int main(int argc,char *argv[]){
	
	int pid=fork();
	if(pid==0){
		sleep(1);
		printf("chlid pid=%d,ppid=%d\n",getpid(),getppid());
	}else{
		printf("==========parent\n");
	}

return 0;
}

在这里插入图片描述

//僵尸进程
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
int main(int argc,char *argv[]){
	
	int pid=fork();
	if(pid==0){
		sleep(1);
		printf("chlid pid=%d,ppid=%d\n",getpid(),getppid());
	}else{
		while(1){
		printf("==========parent\n");
			}	
	}

return 0;
}

在这里插入图片描述
kill -9 无法杀死僵尸进程 所以得杀死父进程

7.2阻塞函数wait

1:pid_t wait(int* status):等价pid_t waitpid(-1,stauts,0)每次调用只能回收一个

7.2.1参数

参数 含义 说明
pid 等待的进程 <-1:等待进程组为pid的所有进程;-1: 等待任何子进程;0:等待同组的进程;>0:进程为pid 的子进程
status 回收的子进程结束状态 判断正常结束:使用WIFEXITED(status);判断异常结束使用WIFSIGNALED(status);判断暂停使用WIFSTOPPED(status)
options 选项 WNOHANG若子进程没有结束,返回0,不予以等待;若子进程结束,返回该子进程的ID。WUNTRACED若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会。

7.2.2返回值

返回值 含义
-1 失败
其他 等待的PID

7.2.3正常结束:WIFEXITED(status)

参数 含义
非0 正常结束子进程0
WEXITSTATUS(status)取得子**进程exit()**返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏

7.2.4异常结束:WIFSIGNALED(status)

参数 含义
非0 异常结束子进程
2 0 非异常结束子进程
WTERMSIG(status)取得子进程因信号而中止的信号代码
一般会先用 WIFSIGNALED 来判断后才使用此宏

7.2.5暂停:WIFSTOPPED(status)

参数 含义
非0 暂停结束子进程
0 非暂停结束子进程
WSTOPSIG(status)取得引发子进程暂停的信号代码
一般会先用 WIFSTOPPED 来判断后才使用此宏。

7.2.6示例

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc,char *argv[]){
	
	int pid=fork();
	if(pid==0){
		sleep(1);
		printf("chlid pid=%d,ppid=%d\n",getpid(),getppid());
	}else{
		printf("parent pid=%d,ppid=%d\n",getpid(),getppid());
		//
		int status;
		pid_t wpid=wait(&status);
		if(WIFEXITED(status)){
			printf("exit value %d\n",WIFEXITED(status));
		}
		
		if(WIFSIGNALED(status)){
			printf("exit by signal %d\n",WIFSIGNALED(status));
		}
		printf("dead_child pid=%d\n",wpid);
	}

return 0;
}

结果:
在这里插入图片描述

7.3waitpid

在这里插入图片描述

发布了30 篇原创文章 · 获赞 4 · 访问量 2021

猜你喜欢

转载自blog.csdn.net/weixin_45639955/article/details/104358515