C++并行与分布式编程chater3 将C++程序分成多个任务

Parallel and Distributed Programming Using C++(C++并行与分布式编程)

Author: Cameron Hughes/ Tracey Hughes

创建进程

为运行任何程序,操作系统必须首先创建进程。当一个新进程被创建时,在主进程表中放入了一个新的入口。创建和初始化一个新的PCB,其进程标识部分包含一个唯一的进程id和父进程id。程序计数器被设置成指向程序的入口点,系统堆栈指针被设置成定义进程的堆栈边界。缺省情况下给进程最低的优先级值,进程最初没有任何资源,除非存在显示的资源请求或者从他们的创建者进程中继承了资源。进程的状态为可运行的,并且放入到可运行或者就绪队列中。系统为进程分配了地址空间,默认情况下这由进程的类型来决定,也可以由创建者指定。

init进程是所有用户进程的父进程。init进程是UNIX系统启动时,对UNIX系统可见的第一个进程。init进程启动系统,必要时运行其他程序,并启动守护程序(daemon)。Init进程的PID为1。

子进程可以使用它自己的可执行映像(executable image)或作为父进程的复制品来创建。作为父进程的复制品,子进程可以继承父进程中的许多属性,包括环境变量、优先级、调度策略、资源限制、打开的文件以及共享内存段等。如果子进程创建之后,父进程分配了一些资源,这些资源对子进程是不可访问的。子进程分配的资源父进程也不可见。数据段是复制的,而不是共享的,所以子进程可以改变它的变量值,而不影响父进程。子进程和父进程共享文本段,并且在创建子进程的系统调用后立即执行指令,他不会执行那些处于上锁阶段的指令,因为这些指令和加载在存储器中的所有其他进程竞争用处理器。

子进程一旦被创建,它的可执行映像就能用另一个可执行映像来替换。文本段、数据段、堆栈段以及它的堆都会被新进程映像覆盖。这个新进程保留它自己的PID和PPID。在可执行映像被替换之前打开的文件,在可执行映像被替换后仍旧保持打开,这个新进程将使用相同的文件许可权限创建文件。CPU时间不会被重设。

使用fork()函数

fork()调用创建一个新的进程,该进程是调用进程(父进程)的复制品。如果调用成功,fork()返回两个值,未子进程返回0,为父进程返回子进程的PID。父进程和子进程从fork()调用之后的指令继续执行。

使用系统调用的exec家族

exec家族用新进程映像取代调用进程映像。新进程映像是一个规则的可执行文件并立即执行。fork()使用父进程的复制品创建并初始化子进程,随后用exec来替换它的进程映像。有六个不同的函数。

使用system()产生进程

system()会导致执行fork-exec和shell。Int system(const char *string);如果调用成功则返回命令的终止状态或返回程序的结果值。

#include <stdlib.h>

int RtValue = fork();

//if(RtValue == 0){

// execl("~/Code/C","proc","",NULL);

//}

system("~/Code/C/proc");

//system("pstree -h");

char *getenv(const char *name)//获取环境变量的值

int setenv(const char *name, const char *value, int overwrite)//设置环境变量

产生进程的POSIX函数

int posix_spawn()从指定的进程映像创建一个新的子进程,可以对子进程进行更细微的设置。

#include <spawn.h>

#include <errno.h>

posix_spawnattr_t X;

posix_spawn_file_actions_t Y;

pid_t Pid;

//command and parameters that the new process will execute

char *const argv[]={"/bin/ps","-lf",NULL};

char *const envp[]={"PROCESSES=2"}; //enviroment list

posix_spawnattr_init(&X);

posix_spawn_file_actions_init(&Y);

posix_spawn(&Pid,"/bin/ps",&Y,&X,argv,envp);

perror("posix_spawn"); //it will display success!

printf("spawn Pid: %d\n",Pid);//show the new process PID

返回结果:

posix_spawn: Success

spawn Pid: 2288

获取进程id

pid_t getpid(void); pid_t getppid(void);

终止进程

当一个进程终止时,PCB被删除,进程所使用的地址空间和资源被释放。退出码放到主进程表中该终止进程的入口。一旦父进程已接受该退出码,这个入口就会被删除。进程终止的情况:所有指令已经执行,进程显式返回或进行终止进程的系统调用,当父进程终止时子进程可能自动终止,父进程发出终止其子进程的信号。非正常终止的情况:进程需要的存储器容量超出了系统的提供能力,进程试图访问一些不允许它访问的资源,进程试图执行一条无效指令或者禁止的计算,若进程是交互的,进程的终止也可以由用户发起。父进程负责其子进程的终止/释放。父进程应该等待,直到所有子进程都已经终止,否则子进程处于僵死状态,直到init进程接收到子进程的退出码。

void exit(int status)使进程正常终止,所有与该进程相关的打开的文件描述符将被关闭,flush所有包含未写入的缓冲数据的打开流。status是进程的退出状态,返回给父进程,父进程只能访问status的低8位数据。

void abort(void)导致进程的非正常终止,与在所有的打开流上执行fclose有相同效果。当进程碰到程序不能处理的错误时,该进程只能异常终止。

#include <signal.h>

int kill(pid_t pid, int sig);用于想pid进程发送信号,当sig未SIGKILL时,终止相应的进程。

进程资源

资源是进程在任何给定的时间使用的任何东西,以作为数据的源,或处理、计算、显示数据或信息的一种方式,如子例程、文件、信号量(semaphore)、互斥锁(mutex)、键盘以及显示屏。处理器就是一个共享资源,只有资源被释放后才允许另一个进程访问,这个资源就是非共享的,进程必须互斥的访问这类资源。资源分配图是有向图。操作系统在进程使用资源上设置了硬限制,进程可以设置或改变它的软限制,但软限制不能超过硬限制。setrlimit(int resource, const struct rlimit *rlp);为指定资源的消费量设置限制,可以设置硬限制,也可以设置软限制。 resource表示资源类型, struct rlimit *rlp设置资源的数量。getrusage()函数返回调用进程使用的资源尺寸信息。

#include <sys/resource.h>

struct rlimit R_limit;

struct rlimit R_limit_values;

R_limit.rlim_cur = 2000;//当前或软限制

R_limit.rlim_max = RLIM_SAVED_MAX;//硬限制设置为最大硬限制

setrlimit(RLIMIT_FSIZE,&R_limit);//设置进程可以创建文件的大小

getrlimit(RLIMIT_FSIZE,&R_limit_values);//获取资源限制信息

printf("file size soft limit: %d\n",(int)R_limit_values.rlim_cur);

异步进程(asynchronous)彼此独立的执行,同步(synchronous)进程交替执行。使用fork,fork-exec和posix_spawn()创建的进程是异步的,system()创建的进程是同步的,将创建一个shell来执行系统命令或可执行文件,父进程挂起,直到子进程终止和system()调用返回。异步进程可以通过执行wait函数挂起执行,在子进程终止之后,等待父进程收集子进程的退出状态,防止僵死进程。pid_t wait(int *status)/ pid_t waitpid(pid_t pid, int *status, int options)

程序分解为多个任务

1.将程序分成创建大量子进程的父进程

2.将程序分成一组独立的二进制文件

3.将程序分成多种类型的进程,每种类型的进程中,每个进程负责创建某种需要的进程

相关程序:process.c

#include <stdlib.h>
#include <spawn.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/resource.h>


int main(){
printf("hello!\n");
id_t pid = 0;
//int which = PRIO_PROCESS; //get the priority of current process
int which = PRIO_USER; //get the user priority
int nice_value;
nice_value = getpriority(which,pid);
printf("current process nice value is: %d\n",nice_value);
//int RtValue = fork();
//if(RtValue == 0){
//    execl("~/Code/C","proc","",NULL);
//}
//system("~/Code/C/proc");
//system("pstree -h");
posix_spawnattr_t X;
posix_spawn_file_actions_t Y;
pid_t Pid;
//command and parameters that the new process will execute
char *const argv[]={"/bin/ps","-lf",NULL};
char *const envp[]={"PROCESSES=2"}; //enviroment list
posix_spawnattr_init(&X);
posix_spawn_file_actions_init(&Y);
posix_spawn(&Pid,"/bin/ps",&Y,&X,argv,envp);
perror("posix_spawn"); //it will display success!
printf("spawn Pid: %d\n",Pid);//show the new process PID

struct rlimit R_limit;
struct rlimit R_limit_values;

R_limit.rlim_cur = 2000;//当前或软限制
R_limit.rlim_max = RLIM_SAVED_MAX;//硬限制设置为最大硬限制
setrlimit(RLIMIT_FSIZE,&R_limit);//设置进程可以创建文件的大小
getrlimit(RLIMIT_FSIZE,&R_limit_values);//获取资源限制信息
printf("file size soft limit: %d\n",(int)R_limit_values.rlim_cur);

return (0);
}
makefile:

#objects = main.o kbd.o command.o display.o \
#        insert.o search.o files.o utils.o

#edit : $(objects)
#    cc -o edit $(objects)

#只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中=“隐晦规则”
#$(objects) : defs.h
#kbd.o command.o files.o : command.h
#display.o insert.o search.o files.o : buffer.h

#.PHONY表示,clean是个伪目标文件
#.PHONY : clean
#clean :
#    rm edit $(objects)
objects = process.o#tab!

proc : $(objects)
cc -o proc $(objects)#tab!

$(objects):

.PHONY : clean
clean :
rm edit $(objects)

本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

转载于:https://www.cnblogs.com/aquar/archive/2010/11/12/3451391.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值