ARM的嵌入式Linux移植体验之应用实例

时间:2012-05-11来源:网络

执行结果为:

Thisischildprocess

Thisischildprocess

Thisisparentprocess

Thisisparentprocess

fork在英文中是分叉的意思,一个进程在运行中,如果使用了fork,就产生了另一个进程,于是进程就分叉了。当前进程为父进程,通过fork()会产生一个子进程。对于父进程,fork函数返回子程序的进程号而对于子程序,fork函数则返回零,这就是一个函数返回两次的本质。

exec

在Linux中可使用exec函数族,包含多个函数(execl、execlp、execle、execv、execve和execvp),被用于启动一个指定路径和文件名的进程。exec函数族的特点体现在:某进程一旦调用了exec类函数,正在执行的程序就被干掉了,系统把代码段替换成新的程序(由exec类函数执行)的代码,并且原有的数据段和堆栈段也被废弃,新的数据段与堆栈段被分配,但是进程号却被保留。也就是说,exec执行的结果为:系统认为正在执行的还是原先的进程,但是进程对应的程序被替换了。

fork函数可以创建一个子进程而当前进程不死,如果我们在fork的子进程中调用exec函数族就可以实现既让父进程的代码执行又启动一个新的指定进程,这很好。fork和exec的搭配巧妙地解决了程序启动另一程序的执行但自己仍继续运行的问题,请看下面的例子:

charcommand[MAX_CMD_LEN];

voidmain()

{

intrtn;/*子进程的返回数值*/

while(1)

{

/*从终端读取要执行的命令*/

printf(>);

fgets(command,MAX_CMD_LEN,stdin);

command[strlen(command)-1]=0;

if(fork()==0)

{

/*子进程执行此命令*/

execlp(command,command);

/*如果exec函数返回,表明没有正常执行命令,打印错误信息*/

perror(command);

exit(errorno);

}

else

{

/*父进程,等待子进程结束,并打印子进程的返回值*/

wait(rtn);

printf(childprocessreturn%dn,rtn);

}

}

}

这个函数实现了一个shell的功能,它读取用户输入的进程名和参数,并启动对应的进程。

clone

clone是Linux2.0以后才具备的新功能,它较fork更强(可认为fork是clone要实现的一部分),可以使得创建的子进程共享父进程的资源,并且要使用此函数必须在编译内核时设置clone_actually_works_ok选项。

clone函数的原型为:

intclone(int(*fn)(void*),void*child_stack,intflags,void*arg);

此函数返回创建进程的PID,函数中的flags标志用于设置创建子进程时的相关选项。

来看下面的例子:

intvariable,fd;

intdo_something(){

variable=42;

close(fd);

_exit(0);

}

intmain(intargc,char*argv[]){

void**child_stack;

chartempch;

variable=9;

fd=open(test.file,O_RDONLY);

child_stack=(void**)malloc(16384);

printf(Thevariablewas%dn,variable);

clone(do_something,child_stack,CLONE_VM|CLONE_FILES,NULL);

sleep(1);/*延时以便子进程完成关闭文件操作、修改变量*/

printf(Thevariableisnow%dn,variable);

if(read(fd,tempch,1)1){

perror(FileReadError);

exit(1);

}

printf(Wecouldreadfromthefilen);

return0;

}

运行输出:

Thevariableisnow42

FileReadError

程序的输出结果告诉我们,子进程将文件关闭并将变量修改(调用clone时用到的CLONE_VM、CLONE_FILES标志将使得变量和文件描述符表被共享),父进程随即就感觉到了,这就是clone的特点。

sleep

函数调用sleep可以用来使进程挂起指定的秒数,该函数的原型为:

unsignedintsleep(unsignedintseconds);

该函数调用使得进程挂起一个指定的时间,如果指定挂起的时间到了,该调用返回0;如果该函数调用被信号所打断,则返回剩余挂起的时间数(指定的时间减去已经挂起的时间)。

exit

系统调用exit的功能是终止本进程,其函数原型为:

void_exit(intstatus);

_exit会立即终止发出调用的进程,所有属于该进程的文件描述符都关闭。参数status作为退出的状态值返回父进程,在父进程中通过系统调用wait可获得此值。

wait

wait系统调用包括:

pid_twait(int*status);

pid_twaitpid(pid_tpid,int*status,intoptions);

wait的作用为发出调用的进程只要有子进程,就睡眠到它们中的一个终止为止;waitpid等待由参数pid指定的子进程退出。

Linux的进程间通信(IPC,InterProcessCommunication)通信方法有管道、消息队列、共享内存、信号量、套接口等。套接字通信并不为Linux所专有,在所有提供了TCP/IP协议栈的操作系统中几乎都提供了socket,而所有这样操作系统,对套接字的编程方法几乎是完全一样的。管道分为有名管道和无名管道,无名管道只能用于亲属进程之间的通信,而有名管道则可用于无亲属关系的进程之间;消息队列用于运行于同一台机器上的进程间通信,与管道相似;共享内存通常由一个进程创建,其余进程对这块内存区进行读写;信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。

下面是一个使用信号量的例子,该程序创建一个特定的IPC结构的关键字和一个信号量,建立此信号量的索引,修改索引指向的信号量的值,最后清除信号量:

#include

#include

#include

#include

1 2 3 4 5

关键词: 应用 实例 体验 移植 嵌入式 Linux ARM

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版