关闭

LINUX 进程控制程序设计

398人阅读 评论(0) 收藏 举报
分类:

1、获取ID

//包含两个头文件

#include <sys/types.h>
#include <unistd.h>


vpid_t getpid(void)       //获取本进程ID。

      //vpid_t是Linux下的进程号类型,其实是宏定义的unsigned int类型

头文件:旧版本\Linux系统下:unistd.h,在VC++6.0下可以用process.h
函数原型:旧的原型为pid_t getpid(void);,推荐使用int _getpid( void );这种形式。注意,函数名第一个字符是下划线。
函数说明:getpid函数用来取得目前进程的进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。
返回值:目前进程的进程识别码

pid_t getppid(void)      //获取父进程ID。

      //pid_t是Linux下的进程号类型,也就是Process ID _ Type 的缩写。 其实是宏定义的unsigned int类型

相关函数 fork,kill,getpid
表头文件 #include<unistd.h>
定义函数 pid_t getppid(void);
函数说明 getppid()用来取得目前进程的父进程识别码。
返回值 目前进程的父进程识别码。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
    printf( "PID = %d\n", getpid() );
    printf( "PPID = %d\n", getppid() );
    return 0;
}


2、进程创建-fork

#include <unistd.h>

#include <sys/types.h>
pid_t fork(void)

功能:创建子进程
fork的奇妙之处在于它被调用一次,却返回两次,它可能有三种不
同的返回值:
1). 在父进程中,fork返回新创建的子进程的PID;
2). 在子进程中,fork返回0;
3). 如果出现错误,fork返回一个负值

头文件:

#include<unistd.h>

#include<sys/types.h>

函数原型:pid_t forkvoid);(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)

返回值: 若成功调用一次则返回两个值,子进程返回0,返回子进程ID;否则,出错返回-1

fork.c

#include <sys/types.h>
#include <unistd.h>
main()
{
    pid_t pid;
    /*此时仅有一个进程*/
    pid=fork();
    /*此时已经有两个进程在同时运行*/
    if(pid<0)
         printf("error in fork!");
    else if(pid==0)
         printf("I am the child process, ID is %d\n",getpid());
    else
         printf("I am the parent process,ID is %d\n",getpid());
}

代码解读:在pid=fork()之前,只有一个进程在执行,但在这条语句执行之后,就变成两个进程在执行了,这两个进程的共享代码段,将要执行的下一条语句都是if(pid==0)。 两个进程中,原来就存在的那个进程被称作“父进程”,新出现的那个进程被称作“子进程”,父子进程的区别在于进程标识符(PID)不同。


3、进程创建-vfork

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void)

功能:创建子进程。


fork PK vfork

区别:
1. fork:子进程拷贝父进程的数据段
vfork:子进程与父进程共享数据段
2. fork:父、子进程的执行次序不确定
vfork:保证子进程先运行,在调用exec或_exit之前与 父进程数据是共享的,在它调用exec或_exit之后 父进程才可能被调度运行。

3、当需要改变共享数据段中变量的值,则拷贝父进程。

#include <unistd.h>
#include <stdio.h>
int main(void)
{
    pid_t pid;
    int count=0;
    pid = vfork();
    count++;
    printf( “count = %d\n", count );
    return 0;
}


4、exec函数族

exec用被执行的程序替换调用它的程序。
区别:
fork创建一个新的进程,产生一个新的PID。exec启动一个新程序,替换原有的进程,因此进程的PID不会改变。

说是exec系统调用,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

int execve(const char *path, char *const argv[], char *const envp[]);

其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

1)

#include<unistd.h>
int execl(const char * path,const char * arg1, ....)
参数:
path:被执行程序名(含完整路径)。
arg1 – argn: 被执行程序所需的命令行参数,含程序名。以空指针(NULL)结束。
函数说明:execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针所指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]... 最后一个参数须用空指针NULL作结束。

execl.c

#include <unistd.h>
main()
{
    execl(“/bin/ls”,”ls”,”-al”,”/etc/passwd”,(char * )0);
}

2)

#include<unistd.h>
int execlp(const char * path,const char * arg1, ...)

函数说明:execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了.
参数:
path:被执行程序名(不含路径,将从path环境变量中查找该程序)。
arg1 – argn: 被执行程序所需的命令行参数,含程序名。以空指针(NULL)结束。

返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。

execlp.c

#include<unistd.h>
main()
{
    execlp(”ls”,”ls”,”-al”,”/etc/passwd”,(char *)0);
}

3)

#include<unistd.h>
int execv (const char * path, char * const argv[ ])

功 能: 装入并运行其它程序的函数
参数:
path:被执行程序名(含完整路径)。
argv[]: 被执行程序所需的命令行参数数组。

#include <unistd.h>
main()
{
    char * argv[ ]={“ls”,”-al”,”/etc/passwd”,(char*)0};
    execv(“/bin/ls”,argv);
}

4)

#include<unistd.h>
int execvp(const char *file ,char * const argv []);
函数说明:
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
错误代码:
EACCES
1. 欲执行的文件不具有用户可执行的权限。
2. 欲执行的文件所属的文件系统是以noexec 方式挂上。
3.欲执行的文件或script翻译器非一般文件。
EPERM
1.进程处于被追踪模式,执行者并不具有root权限,欲执行的文件具有SUID 或SGID 位。
2.欲执行的文件所属的文件系统是以nosuid方式挂上,欲执行的文件具有SUID 或SGID 位元,但执行者并不具有root权限。
E2BIG 参数数组过大
ENOEXEC 无法判断欲执行文件的执行文件格式,有可能是格式错误或无法在此平台执行。
EFAULT 参数filename所指的字符串地址超出可存取空间范围。
ENAMETOOLONG 参数filename所指的字符串太长。
ENOENT 参数filename字符串所指定的文件不存在。
ENOMEM 核心内存不足
ENOTDIR 参数filename字符串所包含的目录路径并非有效目录
EACCES 参数filename字符串所包含的目录路径无法存取,权限不足
ELOOP 过多的符号连接
ETXTBUSY 欲执行的文件已被其他进程打开而且正把数据写入该文件中
EIO I/O 存取错误
ENFILE 已达到系统所允许的打开文件总数。
EMFILE 已达到系统所允许单一进程所能打开的文件总数。
EINVAL 欲执行文件的ELF执行格式不只一个PT_INTERP节区
EISDIR ELF翻译器为一目录
ELIBBAD ELF翻译器有问题。

execvp.c

#include<unistd.h>
main()
{
   char * argv[ ] ={ “ls”,”-al”,”/etc/passwd”,0};
   execvp(“ls”,argv);
}

5)

#include<unistd.h>

int execve(const char * filename,char * const argv[ ],char * const envp[ ]);

函数说明:execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。

返回值:

如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
错误代码EACCES
1. 欲执行的文件不具有用户可执行的权限。
2. 欲执行的文件所属的文件系统是以noexec 方式挂上。
3.欲执行的文件或script翻译器非一般文件。
EPERM
1.进程处于被追踪模式,执行者并不具有root权限,欲执行的文件具有SUID 或SGID 位。
2.欲执行的文件所属的文件系统是以nosuid方式挂上,欲执行的文件具有SUID 或SGID 位元,但执行者并不具有root权限。
E2BIG 参数数组过大
ENOEXEC 无法判断欲执行文件的执行文件格式,有可能是格式错误或无法在此平台执行。
EFAULT 参数filename所指的字符串地址超出可存取空间范围。
ENAMETOOLONG 参数filename所指的字符串太长。
ENOENT 参数filename字符串所指定的文件不存在。
ENOMEM 核心内存不足
ENOTDIR 参数filename字符串所包含的目录路径并非有效目录
EACCES 参数filename字符串所包含的目录路径无法存取,权限不足
ELOOP 过多的符号连接
ETXTBUSY 欲执行的文件已被其他进程打开而且正把数据写入该文件中
EIO I/O 存取错误
ENFILE 已达到系统所允许的打开文件总数。
EMFILE 已达到系统所允许单一进程所能打开的文件总数。
EINVAL 欲执行文件的ELF执行格式不只一个PT_INTERP节区
EISDIR ELF翻译器为一目录
ELIBBAD ELF翻译器有问题。
execve.c

#include<unistd.h>
main()
{
    char * argv[ ]={"ls","-al","/etc/passwd",(char *)0};
    char * envp[ ]={"PATH=/bin",0};
    execve("/bin/ls",argv,envp);
}

6)

#include<unistd.h>

int execle(const char * path,const char * arg,....,char *const envp[]);

函数说明:
execl()用来执行参数path字符串所代表的文件路径,并为新程序复制最后一个参数所指示的环境变量。接下来的参数代表执行该文件时传递过去的argv(0)、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。

5、

#include <stdlib.h>
int system( const char* string )
功能:
调用fork产生子进程,由子进程来调用
/bin/sh -c string来执行参数string所代表
的命令。

system.c

#include <stdlib.h>
void main()
{
    system(“ls -al /etc/passwd”);
}
6、进程等待
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int * status)
功能:
阻塞该进程,直到其某个子进程退出。

wait.c

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
void main()
{
   pid_t pc,pr;
   pc=fork();
   if (pc==0){ /* 如果是子进程 */
       printf(“This is child process with pid of %d\n”,getpid());
       sleep(10); /* 睡眠10秒钟 */
   }
   else if (pc>0){ /* 如果是父进程 */
       pr=wait(NULL); /* 等待 */
       printf("I catched a child process with pid of %d\n"),pr);
   }
   exit(0);
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:65285次
    • 积分:1621
    • 等级:
    • 排名:千里之外
    • 原创:93篇
    • 转载:54篇
    • 译文:1篇
    • 评论:3条
    最新评论