通过getpid获取当前进程号
sys
pid = 0;交换进程,起着进程调度、资源分配作用
pid = 1;init进程, 系统初始化 譬如界面,
exit():函数exit()“立即”终止调用进程、进程中任何开的文件都被关闭;、进程的任何子进程被进程继承,
wait(&status)等待退出状态、整体长退出用WEXITSTAYUS(status);
waitpid(pid,&status,WNOHANG);//子进程pid,状态值、不挂起WNOHANG
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid_t pid2;
pid_t retpid;
pid = getpid(); //获取当前pid
printf("befer pid:%d\n",pid);
retpid = fork(); //把fork的pid返回给retpid 如果大于0 就是当前进程 等于0是子进程
pid2 = getpid();
printf("after pid:%d\n",pid2);
if(pid == pid2){ //第一次的两个pid相等在父进程中,第二次不等在子进程中
printf("this is father pid:%d,retpid:%d\n",getpid(),retpid);
}
else{
printf("this is child pid:%d,retpid:%d\n",getpid(),retpid);
}
return 0;
}
存储空间分配
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()//创建进程不断输入 输入为1 产生一个子进程 父进程什么都不干 让子进程干活
{
int data;
pid_t pid;
while(1){
printf("qing shu ru data\n");
scanf("%d",&data);
if(data == 1){
pid = fork();
if(pid > 0){ //父进程
}
else if(pid == 0){ //子进程不断打印
while(1){
printf("this is child pid:%d\n",getpid());
sleep(2);
}
}
}
else{
// printf("shu ru de bu shi 1\n");
}
}
return 0;
vfork使用方法,用exit退出、break退出会打乱cnt
#include <unistd.h>
#include <stdlib.h>
#incldue <stdio.h>
int main() //vfork 会先执行子进程 且共用一块内存 会改变数据的值用exit退出 否则破坏cnt值
{
pid_t pid;
int cnt = 0;
pid = vfork();
if(pid > 0){
while(1){
printf("this is the father pid:%d\n",getpid());
sleep(2);
printf("this is father cnt:%d\n",cnt);
}
}
else if(pid == 0){ //先执行子进程
while(1){
printf("this is the child pid:%d\n",getpid());
sleep(2);
cnt++;
printf("cnt=%d\n",cnt);
if(cnt == 5){
exit(-1); //退出子进程 去执行父进程
}
}
}
return 0;
}
10中 进程退出:正常、异常退出
正常退出:main中return、调用exit(0)-----标准c库 会对数据处理保存后再退出,
_exif/Exit数据直接退出、线程执行结束---进程结束退出、调用函数pthread_
异常退出:调用abrt、ctel+c、线程取消
进程退出 :使用同一段退出代码,该代码段--是关闭相应进程的 打开描述符。关闭后并释放内存
父进程通过子进程退出的返回状态判断是否正常退出、活做了多少用wait卡住状态 跟vfork有点类似
//wait等待退出的用法 wait(&status),WEXITSTATUS(status)、exit(5)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = fork(); //产生一个子进程 用wait等待
int status = 10; //当status的值和exit退出值相等时说明 子进程正常结束
// pid_t wait(int *status);
if(pid > 0){ //父进程等待 子进程结束wait取status地址等待
int num = wait(&status); //wait(null)也等待 但是不关系子进程退出状态
printf("wait num = %d\n",num); //wait返回值num是子进程的pid号
printf("fther wait status = %d\n",WEXITSTATUS(status)); //判断status与
//exit是否相等
while(1){
printf("this is the father pid:%d\n",getpid());
sleep(2);
}
}
else if(pid == 0){
while(1){
printf("this is the child pid:%d\n",getpid());
sleep(2);
cnt++;
printf("cnt=%d\n",cnt);
if(cnt == 5){
exit(5); //子进程 先执行结束退出 把5传递给wait的status
}
}
}
return 0;
}
僵尸进程:父进程不收集子进程退出状态
孤儿进程:子进程还未结束 父进程先结束了
waitpid(pid,&status,WNOHANG);用法和孤儿进程
//僵尸进程 和孤儿进程
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
pid = fork();
int cnt = 0;
int status = 10;
// pid_t waitpid(pid_t pid, int *status, int options);
if(pid > 0){ //子进程还没结束父进程就先结束了
printf("this is father pid:%d\n",getpid());
}
else if(pid == 0){ //子进程
while(1){ //子进程用getppid打印父进程 第二次之后为1 用init函数收集父进程状态
//init收留 防止产生更多的孤儿进程
printf("this is child pid:%d\nfathepid:%d\n",getpid(),getppid());
cnt++;
printf("cnt = %d\n",cnt);
if(cnt == 5){
exit(5);
}
sleep(2);
}
}
return 0;
}
exec族函数:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
//exex族函数 调用成功直接运行族函数中的可执行文件,不反回,错误返回-1
//exexl exexlp execvp
#include <stdio.h>
#include <unistd.h>
int main()
{
// int execl(const char *path, const char *arg, ...);//注意exexl四个参数
if(execl("./echarg","echarg","aa",NULL) == -1){ //成功直接执行 调用的可执行文件
printf("exec error!!\n"); //错误返回-1
perror("why:");
}
printf("mei you diao yong chenggong\n");
return 0;
}
int main()
{
// int execl(const char *path, const char *arg, ...);
if(execl("/bin/ps","ps","-aux",NULL) == -1){ //exexl参数(路径、文件名、传参、
// NULL结尾)
printf("exec error!!\n");
perror("why:");
}
printf("mei you diao yong chenggong\n");
return 0;
}
int main()
{
// int execl(const char *path, const char *arg, ...);
if(execlp("date","date",NULL,NULL) == -1){ //exexlp不用加路劲 PATH已近声明
printf("exec error!!\n");
perror("why:");
}
printf("mei you diao yong chenggong\n");
return 0;
}
int main()
{
// int execvp(const char *file, char *const argv[]);
char *argv[] = {"data",NULL,NULL};
if(execvp("date",argv) == -1){ //execvp两个参数 封装
printf("exec error!!\n");
perror("why:");
}
printf("mei you diao yong chenggong\n");
return 0;
}
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[])
int execle(const char *path, const char *arg,..., char * const envp[]);
exec族函数函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
返回值:
exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录
main函数中fork打开子进程,在子进程中exrcl("./changeData","changeData","test.txt",NULL)
直接写到if里面不够灵活,因为我们只能把子进程的程序代码粘贴过来执行,这样必须知道源代码,太长了也不好控制,比如希望子进程执行ls -a,这样是不行的,因为ls的源代码没有这样ls放在子进程里面就实现不了,
此时就是用exec族函数,可以直接把一个编译好的可执行程序,直接加载运行
//fork创建子进程 在子进程中用execl函数执行可执行文件
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid;
int data;
while(1){
scanf("%d",&data);//不要加换行
printf("please input!\n");
if(data == 1){ //输入为1 创建子进程
pid = fork();
printf("password");
if(pid > 0){
wait(NULL);//只要有等待就不会成为僵尸进程
}
else if(pid == 0){ //在子进程中调用changeData函数 传过去txt文件修改
execl("./changeData","changeData","config.txt",NULL);
}
}
}
return 0;
}
/*
int main() //execl执行的changeData程序
{
int fd;
char *readBuf;
fd = open("./config.txt",O_RDWR|O_CREAT,0600);
int size = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*size + 8);
read(fd,readBuf,size);
char *p = strstr(readBuf,"LENG=");
if(p == NULL){
printf("mei zhao dao !\n");
}
p = p+strlen("LENG=");
*p = '5';
p = p+sizeof(char);
*p = '5';
lseek(fd,0,SEEK_SET);
write(fd,readBuf,strlen(readBuf));
close(fd);
}
*/
system函数使用方法
#include <stdio.h>
#include <stdlib.h>
int main()
{ //system和exex函数大致相同
//成功返回进程pid 不能返回时返回127 失败返回-1
if(system("ls -l") == -1){ //先执行system函数 结束后 返回继续执行其他
printf("erro\n");
perror("why:\n");
}
printf("da yin cheng gong\n");
return 0;
}
popen函数用法
//pipe exec system一般用于子进程中执行可以执行文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//pipe是流(只能r/w) 返回文件类型 用fread把里面内容读出来 并打印
// FILE *popen(const char *command, const char *type);
FILE *fp;
char str[1024] = {0}; //用于存放读取文件
fp = popen("ps -aux|grep ./a.out","r"); //pipo可以获取输出结果 返回文件类型
// size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int n_fread = fread(str,1,1024,fp); //流 用fread获取内容
printf("n_read:%d str:%s\n",n_fread,str);//打印
fclose(fp);
return 0;
}