17.Linux 进程(一)

  • Post author:
  • Post category: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


-新程序没有执行权限



版权声明:本文为m0_57908316原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。