操作系统同时运行多个程序
程序:就是一个静态的文件
进程:运行着的实体
查看进程之间的关系
pstree
操作系统如何区分进程
PID:进程的身份证
查看PID:
ps -ef | more
创建一个进程
如果要创建一个新进程:则需要用到一个fork函数
使用fork函数必须包含头文件:
#include <unistd.h>
函数原型:pid_t fork(void);
返回值:
成功:0或其他正整数
失败:-1
fork函数特性
①执行fork函数之后,fork函数会返回两次
②父进程返回正整数子进程返回0
在旧进程中返回时,返回值为0
在新进程返回时,返回值为进程的pid(进程的身份证号码)
fork函数创建一个新进程不如叫复制新进程
fork函数要点总结
在执行fork函数之前,操作系统只有一个进程,fork函数之前的代码只会被执行一次。
在执行fork函数之后,操作系统有两个几乎一样的进程,fork函数之后会被执行两次。
先创建
system_program
文件夹用来存放以后我们系统编程的实验文件
sudo mkdir part_1
sudo cp ../IO_program/part_3/Makefile ./part_1
下面这个是写错了的,不过我们可以把它移到part_1
sudo cp ../IO_program/part_3/Makefile ./
sudo mv Makefile part_1/
下面是验证
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t i;
printf("before fork!\r\n");
i = fork();
printf("after fork:i=%d\r\n",i);
return 0;
}
ARCH ?= X86
ifeq ($(ARCH),X86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=test_fork
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
~
fork:i=2903:新进程打印出来
fork:i=0:返回值为0说明是老进程
子进程偷梁换柱
exec函数族
常用后缀:
l:代表以列表形式传参
v:代表以形式传参(vector)
p:代表使用环境变量Path来寻找指定执行文件
e:代表用户提供
使用exec函数族需要包含头文件:#include <unistd.h>
函数原型:
int execl(const char *path, const char *arg, …)
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
result=fork();
如果result的值是在子进程里面,则result的值大于0,实际上是替换了父进程的程序
if(result > 0)
{
execl("/bin/ls","ls","-l",NULL);
printf("error!!\r\n");
return -1;
}
return 0;
}
ARCH ?= X86
ifeq ($(ARCH),X86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=test_execl
#OBJS=main.o mp3.o
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
int execlp(const char *file, const char *arg, …)
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
result=fork();
if(result > 0)
{
execlp("ls","ls","-l",NULL);
printf("error!!\r\n");
return -1;
}
return 0;
}
ARCH ?= X86
ifeq ($(ARCH),X86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=test_execlp
#OBJS=main.o mp3.o
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
~
execv:
int execv(const char *path,char *const argv[])
返回值:
成功:不返回
失败:-1
从
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
char *arg[]={"ls","-l",NULL}; //指针数组,里面放字符串
result=fork();
if(result > 0)
{
execv("/bin/ls",arg);//传入arg地址
printf("error!!\r\n");
return -1;
}
return 0;
}
ARCH ?= X86
ifeq ($(ARCH),X86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=test_execv
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
execve
int execve(const char *path,char *const argv[],char *const envp[])
返回值:
成功:不返回
失败:-1
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result;
char *arg[]={"env",NULL};
char *env[]={"PATH=/tmp","name=lzf",NULL};
result=fork();
if(result > 0)
{
execve("/usr/bin/env",arg);
printf("error!!\r\n");
return -1;
}
return 0;
}
上面env位置错了
which env
使用exec函数族要点总结:
①i后缀和v后缀必须两者选其一来使用
②p后缀和e后缀是可选的,可用可不用
③组合后缀的相关函数还有很多,可自己进一步了解
④exce函数有可能执行失败,需要预防
-新程序的文件路径出错
-传参或者是自定义环境变量时,没有加NULL
-新程序没有执行权限