进程简介
linux是一个多任务操作系统,这也是与单片机最大的区别,它可以运行多个程序,每个程序都是一个进程,当然一个程序也可能包含多个进程。不同用户在同一操作系统运行的同一个进程,共享一个函数库与程序代码。
在终端输入ps -ef 命令,可查看所有运行的进程
每个进程都有唯一的PID,可以看到PID为1的特殊进程叫做init进程,负责管理其他进程。
进程调度
创建进程fork,vfork
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
pid_t vfork(void);
fork()调用失败返回-1,调用成功则父进程的fork调用返回子进程的PID,子进程fork调用返回0。
fork与vfork区别在于 :
1、fork子进程拷贝了父进程数据段,堆,栈。而vfork子进程共享父进程数据段,堆,栈。
2、vfork子进程先运行,fork子进程父进程执行顺序不定
创建fork.c文件,内容如下
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int global=1;
int main()
{
int v = 0;
switch(fork())
{
case -1://创建 失败
return -1;
case 0://子进程
global=100;//子进程改变全局变量的值
v--; //子进程改变局部变量的值
printf("child pid:%d, g_value:%d, value:%d\n", getpid(), global, v);
exit(0);
break;
default://父进程
sleep(1);
printf("parent pid:%d g_value:%d, value:%d\n", getpid(), global, v);
break;
}
return 0;
}
vfork.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int global=1;
int main()
{
int v = 0;
switch(vfork())
{
case -1://创建 失败
return -1;
case 0://子进程
global = 100;
v--;
printf("child pid:%d,g_value:%d,value:%d\n", getpid(), global, v);
exit(0);
break;
default://父进程
// sleep(1);
printf("parent pid:%d g_value:%d,value:%d\n", getpid(), global, v);
break;
}
return 0;
}
子进程改变了全局变量和局部变量,父进程中也跟着改变了
进程同步
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *stat_loc);
当子进程执行时,wait()可以暂停父进程的执行,使其等待。一旦子进程执行完,等待的父进程就会重新执行。如果有多个子进程在执行,那么父进程中的wait()在第一个子进程结束时返回,恢复父进程执行。
exec 系列调用
当exec 调用成功,调用进程将被覆盖,然后从新程序的入口开始执行。这样就产生了一个新的进程取代了原来的进程,但是它的进程标识符与调用进程相同(PID不变)。
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
例子 建立execl.c内容是:
#include <error.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
if(execl("/mnt/hgfs/share_2019/linux_c/execl/helloexecl", "helloexecl", "123", "abc", NULL) < 0)
{
perror("execl error\n");
return -1;
}
return 0;
}
创建另一c文件 helloexecl.c,打印所有命令行参数。
#include<stdio.h>
int main(int argc,char *argv[])
{
int i = 0;
printf("argc = %d\n", argc);
for(; i < argc; i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
输入命令gcc execl.c 与gcc -o helloexecl helloexecl.c
执行a.out可执行文件
终止进程
#include <unistd.h>
void exit(int status);