17.Linux 进程(一)

操作系统同时运行多个程序

程序:就是一个静态的文件

进程:运行着的实体

查看进程之间的关系

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

-新程序没有执行权限

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值