这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的。

实验题目:Linux环境下的进程控制

实验目的:熟悉并掌握Linux环境下进程的相关函数的应用;守护进程的概念、启动和操作;进程操作程序的编写。

一、Linux进程控制

设计程序,满足如下要求:

1、设计一个程序,要求显示Linux系统分配给此程序的进程号(PID)和它的父进程号(PPID)。

在Linux环境下进程创建时,系统会分配一个唯一的数值给每个进程,这个数值就称为进程标示符(pid),他的父进程号用ppid表示。

在Linux中获取当前进程的pid、ppid可以调用getpid()和getppid()函数。

getpid函数说明如下:

所需头文件 #include<unsitd.h>
函数功能 取得当前进程的进程号
函数原型 pid_t getpid(void)
函数传入值
返回值 成功返回当前进程的标识符
所需头文件
#include<unistd.h>
函数功能 取得当前进程的父进程号
函数原型 pid_t getppid(void)
函数传入值
返回值 成功返回当前进程的父进程标识符
 #include<stdio.h>
#include<unistd.h>
int main()
{
printf("系统分配的进程号(PID)是:%d\n",getpid());
printf("系统分配的父进程号(PPID)是:%d\n",getppid());
return ;
}

2、设计一个程序,用fork函数创建一个子进程,在子进程中给变量n赋值3,在父进程中给变量n赋值6,fork调用之后父进程和子进程的变量message和n被赋予不同的值,互不影响。

Linux下调用fork()函数可以创建一个新进程,由fork创建的新的进程被称为子进程。fork()函数调用一次返回两次,区别是子进程的返回值是0,父进程的返回值是子进程的pid。子进程是父进程的复制品,复制父进程的数据空间,堆栈等。

所需头文件 #include <unistd.h>
功能 建立一个新的进程
   
函数原型 pid_t fork(void)
传入值
返回值

执行成功在子进程中返回0,在父进程中返回子进程的pid,失败返回-1

 #include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
pid_t pid;
char *message;
int n;
pid = fork();
if(pid < )
{
perror("fork failed!\n");
exit();
}
if(pid == )
{
message="This is the child!\n";
n=;
}
else
{
message="This is the parent!\n";
n=;
}
for(;n>;n--)
{
printf(message);
sleep();
} return ;
}

3、分别使用exec函数族中的六个函数执行命令“ifconfig eth0 192.168.110.140”。

#include<stdio.h>
#include<stdlib.h>
//可以分别注释掉不同的exec族函数,分别执行以查看效果。
#include<unistd.h>
#include<sys/types.h> int main()
{
char *const argv[]={"ifconfig","eth0","192.168.110.140",NULL};
char *env[]={"PATH=bin:usr/sbin",NULL};
// execl("/sbin/ifconfig","ifconfig","eth0","192.168.110.140",NULL);
// execv("/sbin/ifconfig",argv);
// execle("/sbin/ifconfig","ifconfig","eth0","192.168.110.140",NULL,env);
// execve("/sbin/ifconfig",argv,env);
// execlp("ifconfig","ifconfig","eth0","192.168.110.140",NULL);
execvp("ifconfig",argv);
return ;
}

在系统中创建一个进程的目的是需要该进程完成一定的任务,需要该进程执行他的程序代码,在Linux系统中可以调用exec函数是程序执行。

系统调用exec有多种使用形式,称为exec族,他们只是在参数上不同,而功能是相同的。

在exec族里面有6个函数可以用来建立子进程,分别是execl, execcv, execle , execve, execlp, execvp,函数中第5、6个字符l, v, e, p表示函数中国的参数分别用列表传递方式,字符传递方式,可制定环境变量及路径自动搜索功能。

所需头文件 #include <unistd.h>
函数原型

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

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

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

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

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

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

返回值 -1出错

而事实上,这六个函数中真正的系统调用函数只有execve(),其他的五个都是库函数,他们最终调用的都是execve这个系统函数。

exec调用举例如下:

 char *const ps_argv[] = {"ps","-o", "pid,ppid",NULL};
char *const ps_envp[] = {"PATH = bin:/usr/bin","TERM = console",NULL}; execl("bin/ps","ps","-o","pid,ppid",NULL);
execv("bin/ps",ps_argv);
execle("bin/ps","ps","-o","pid,ppid",NULL,ps_envp);
execve("bin/ps",ps_argv,ps_envp);
execlp("ps","ps","-o","pid,ppid",NULL);
execvp("ps",ps_argv);

二、僵尸进程

1、设计一个程序,要求创建一个子进程,子进程显示自己的进程号(PID)后暂停一段时间,父进程等待子进程正常结束,打印显示等待的进程号(PID)和等待的进程退出状态。

 #include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t pid,wpid;
int status,i;
pid =fork();
if(pid ==)
{
printf("This is the child,进程号(PID)是:%d\n",getpid());
sleep();
exit();
}
else
{
printf("This is the parent,正在等待子进程.....\n");
wpid=wait(&status);
i=WEXITSTATUS(status);
printf("等待进程的进程号(PID)是:%d,结束状态:%d\n",wpid,i);
}
return ;
}

2、要求子进程用sleep等待10秒,父进程用waitpid函数等待子进程正常结束,父进程在等待的时候不阻塞,每1秒在屏幕上输出一行文字,若发现子进程退出,打印等待进程的进程号(PID)和退出状态。请编写一程序进行调试。

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
pid_t pid,wpid;
int status;
pid=fork();
if(pid==)
{
printf("This is the child,进程号(PID)是:%d\n",getpid());
printf("This is the child,Then slepp now!\n");
sleep();
exit(); }
else
{
printf("This is the parent!\n");
while(){
waitpid(pid, &status, WNOHANG);
printf("Wait for child.........\n");
if( == WIFEXITED(status))
sleep();
else{
printf("Child is end now!\n");
printf("等待的进程的进程号(PID)是:%d,结束状态:%d\n",pid,WEXITSTATUS(status));
break;
}
}
}
}

三、守护进程

1

编写一程序,要求运行后成为守护进程,每隔3秒修改一个本机的IP地址,并在屏幕上显示IP地址信息。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<sys/param.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<signal.h>
void init_daemon(void)
{
pid_t child1,child2;
int i;
child1=fork();
if(child1 >)
exit();
else if(child1 < )
{
perror("创建子进程失败!\n");
exit();
}
setsid();
chdir("/mnt/hgfs/zhaoshun");
umask();
for(i=;i<NOFILE;++i)
close(i);
return;
}
int main()
{
FILE * fp;
char buf1[],buf2[];
init_daemon();
if((fp=fopen("ipadd","r"))=NULL)
{
printf("打开文件出错!\n");
} while() {
ifconfig(); system("ifconfig");
sleep(); } return ; }

【Linux程序设计】之进程控制&守护进程的更多相关文章

  1. Linux中的两种守护进程stand alone和xinetd

    Linux中的两种守护进程stand alone和xinetd --http://www.cnblogs.com/itech/archive/2010/12/27/1914846.html#top 一 ...

  2. Linux进程学习(孤儿进程和守护进程)

    孤儿进程和守护进程 通过前面的学习我们了解了如何通过fork()函数和vfork()函数来创建一个进程.现在 我们继续深入来学习两个特殊的进程:孤儿进程和守护进程 一.孤儿进程 1.什么是 孤儿进程如 ...

  3. Linux进程学习 - 孤儿进程和守护进程

    孤儿进程和守护进程 通过前面的学习我们了解了如何通过fork()函数和vfork()函数来创建一个进程.现在 我们继续深入来学习两个特殊的进程:孤儿进程和守护进程 一.孤儿进程 1.什么是 孤儿进程如 ...

  4. Linux 普通进程 后台进程 守护进程

    一.普通进程与后台进程 默认情况下,进程是在前台运行的,这时就把shell给占据了,我们无法进行其它操作.对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个'& ...

  5. linux usb枚举过程分析之守护进程及其唤醒【转】

    转自:http://blog.csdn.net/xuelin273/article/details/38646765 usb热插拔,即usb设备可以实现即插即用,像U盘一样,插到电脑里就可以用,不用时 ...

  6. Linux 普通进程 后台进程 守护进程(转)

    一.普通进程与后台进程 默认情况下,进程是在前台运行的,这时就把shell给占据了,我们无法进行其它操作.对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个'& ...

  7. Windows 和 Linux 上Redis的安装守护进程配置

    # Windows 和 Linux 上Redis的安装守护进程配置 Redis 简介 ​ Redis是目前最常用的非关系型数据库(NOSql)之一,常以Key-Value的形式存储.Redis读写速度 ...

  8. Linux守护进程列表/守护进程

      在linux或者unix操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程.为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统. ...

  9. 【Linux 进程】孤儿进程、僵尸进程和守护进程

    1.孤儿进程: 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作.孤儿进程是 ...

随机推荐

  1. Mac 制作 10.11.3 U盘安装盘

    U盘要且只分一个区  Mac OS 拓展(日志式)  GUID分区表: 将“安装 OS X El Capitan” 放到  应用程序文件夹下 命令: sudo /Applications/Instal ...

  2. 384. Shuffle an Array

    Shuffle a set of numbers without duplicates. Example: // Init an array with set 1, 2, and 3. int[] n ...

  3. Spring 注释 @Autowired 和@Resource

    一. @Autowired和@Resource都可以用来装配bean,都可以写在字段上,或者方法上. 二. @Autowired属于Spring的:@Resource为JSR-250标准的注释,属于J ...

  4. sql语句的join用法

    sql的join分为三种,内连接.外连接.交叉连接. 以下先建2张表,插入一些数据,后续理解起来更方便一些. create table emp(empno int, name char(20),dep ...

  5. python字符串中插入变量

  6. 重温WCF之数据契约和序列化(四)

    一.数据契约 1.使用数据协定可以灵活控制哪些成员应该被客户端识别. [DataContract] public class Employee { [DataMember] public string ...

  7. android:installLocation = "auto" 的用法

    在Froyo(android 2.2,API Level:8)中引入了android:installLocation.通过设置该属性可以使得开发者以及用户决定程序的安装位置. android:inst ...

  8. WPF中加载高分辨率图片性能优化

    在最近的项目中,遇到一个关于WPF中同时加载多张图片时,内存占用非常高的问题. 问题背景: 在一个ListView中同时加载多张图片,注意:我们需要加载的图片分辨率非常高. 代码: XAML: < ...

  9. WebRTC代码走读(八):代码目录结构

    转载注明出处http://blog.csdn.net/wanghorse ├── ./base //基础平台库,包括线程.锁.socket等 ├── ./build //编译脚本,gyp ├── ./ ...

  10. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

    主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...