我需要 Linux环境高级c语言程序设计教程第二版答案,帮忙找一下教材百度网盘资源呗!

进程概念进程是一个独立的可调度的任务 进程是一个抽象实体。当系统在执行某个程序时,分配和释放的各种资源进程是一个程序的一次执行的过程进程是程序执行和资源管理的最小单位进程和程序的区别程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念进程是一个动态的概念,它是程序执行的过程,包括创建、调度和消亡Linux下的进程结构主要的进程标识进程号(Process Identity Number,PID)父进程号(Parent Process ID,PPID)PID唯一地标识一个进程Linux中的进程包含三个段“数据段”存放的是全局变量、常数以及动态数据分配的数据空间(如malloc函数取得的空间)等。)“正文段”存放的是程序中的代码“堆栈段”存放的是函数的返回地址、函数的参数以及程序中的局部变量进程与程序进程不仅包括程序的指令和数据,而且包括程序计数器值、CPU的所有寄存器值以及存储临时数据的进程堆栈。Linux系统中的进程类型 交互进程:交互式进程:这类进程经常与用户进行交互,需要等待用户的输入(键盘和鼠标操作等)。当接收到用户的输入之后,这类进程能够立刻响应。典型的交互式进程有 shell 命令进程、文本编辑器和图形应用程序 运行等。
批处理进程:这类进程不必与用户进行交互,因此通常在后台运行。因为这类进程通常不必很快地响应,因此往往不会优先调度。典型的批处理进程是编译器的编译操作、数据库搜索引擎等
守护进程:这类进程一直在后台运行,和任何终端都不关联。通常系统启动时开始执行,系统关闭时才结束。很多系统进程(各种服务)都是以守护进程的形式存在 进程运行状态运行态(R):此时进程或者正在运行,或者准备运行。等待态:此时进程在等待一个事件的发生或某种系统资源。 可中断(S) 不可中断(D)停止态(T):此时进程被中止。死亡态(X):这是一个已终止的进程,但还在进程向量数组中占有一个task_struct结构。僵尸态(Z):这是一种特殊的状态,子进程退出时,父进程未回收子进程的资源进程状态图查看进程信息调度进程ps 查看系统中的进程top 动态显示系统中的进程nice 按用户指定的优先级运行进程renice 改变正在运行进程的优先级kill 结束进程(包括后台进程)bg 将挂起的进程在后台执行fg 把后台运行的进程放到前台运行ps 查看系统进程top 查看进程动态信息/proc 查看进程详细信息nice 按用户指定的优先级运行进程linux@linux:~/Desktop/Homework/L1_LinuxC$ nice -n 5 ./test
renice 改变正在运行进程的优先级jobs 查看后台进程bg 将挂起的进程在后台运行fg 把后台运行的进程放到前台运行进程创建 – forkfork函数实际上是完成一个子进程的创建,子进程是对父进程几乎完整的复制,或者说子进程继承了父进程的相关属性;子进程从父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号处理函数、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等备注 :该函数执行成功之后,将会产生一个新的子进程,在新的子进程中其返回值为 0,在原来的父进程中其返回值为大于 0 的正整数,该正整数就是子进程的 PIDint main(int argc, const char *argv[])
{
pid_t fpid; //fpid表示fork函数返回的值
int count = 0;
fpid = fork();
if(fpid < 0)
{
puts(" Error in fork!");
}
else if(fpid == 0)/*返回值为0代表子进程*/
{
printf(" \n I am child process, my process id is %d\n",getpid());
count++;
}
else /*返回值大于0代表父进程*/
{
printf(" \n I am parents process, my process id is %d\n",getpid());
count++;
}
printf(" sum = %d\n ",count);
return 0;
}
运行结果:在语句fpid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的几乎完全相同,将要执行的下一条语句都是if(fpid<0)……为什么两个进程的fpid不同呢,这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:1)在父进程中,fork返回新创建子进程的进程ID;2)在子进程中,fork返回0;3)如果出现错误,fork返回一个负值;在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。引用一位网友的话来解释fpid的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fpid(p 意味point)指向子进程的进程id, 因为子进程没有子进程,所以其fpid为0.fork出错可能有两种原因:1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。2)系统内存不足,这时errno的值被设置为ENOMEM。创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。每个进程都有一个独特(互不相同)的进程标识符(process ID),可以通过getpid()函数获得,还有一个记录父进程pid的变量,可以通过getppid()函数获得变量的值。fork执行完毕后,出现两个进程,有人说两个进程的内容完全一样啊,怎么打印的结果不一样啊,那是因为判断条件的原因,上面列举的只是进程的代码和指令,还有变量啊。执行完fork后,进程1的变量为count=0,fpid!=0(父进程)。进程2的变量为count=0,fpid=0(子进程),这两个进程的变量都是独立的,存在不同的地址中,不是共用的,这点要注意。可以说,我们就是通过fpid来识别和操作父子进程的。还有人可能疑惑为什么不是从#include处开始复制代码的,这是因为fork是把进程当前的情况拷贝一份,执行fork时,进程已经执行完了int count=0;fork只拷贝下一个要执行的代码到新的进程。父子进程子进程继承了父进程的内容父子进程有独立的地址空间,互不影响若父进程先结束:子进程成为孤儿进程,被init进程收养子进程变成后台进程若子进程先结束:父进程如果没有及时回收,子进程变成僵尸进程进程结束 – exit/_exit#include <stdlib.h>#include <unistd.h>void exit(int status);void _exit(int status);|#include<stdlib.h>
int main()
{
printf("this process will exit!");
exit(0);
printf("never be displayed!");
}
int main()
{
printf("Using exit...\n");
printf("This is the end");
exit(0);
}
Using exit…This is the endint main()
{
printf("Using _exit...\n");
printf("This is the end");
_exit(0);
}
Using _exit…_exit和exit的区别_exit()函数的作用最为简单:直接使进程终止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的"清理I/O缓冲"一项。进程 – exec函数族(1)exec 函数族说明。fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容。我们能否让子进程执行一个新的程序呢?exec 函数族就提供了一个在进程中执行另一个程序的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代当前进程的数据段、代码段和堆栈段。在执行完之后,当前进程除了进程号外,其他内容都被替换了。这里的可执行文件既可以是二进制文件,也可以是 Linux 下任何可执行的脚本文件。在 Linux 中使用 exec 函数族主要有两种情况。① 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用 exec 函数族中的任意一个函数让自己重生。② 如果一个进程想执行另一个程序,那么它就可以调用 fork()函数新建一个进程,然后调用 exec 函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。exec函数族使用区别可执行文件查找方式表中的前四个函数的查找方式都是指定完整的文件目录路径,而最后两个函数(以p结尾的函数)可以只给出文件名,系统会自动从环境变量“$PATH”所包含的路径中进行查找。参数表传递方式两种方式:逐个列举或是将所有参数通过指针数组传递以函数名的第五位字母来区分,字母为“l”(list)的表示逐个列举的方式;字母为“v”(vertor)的表示将所有参数构造成指针数组传递,其语法为char *const argv[]环境变量的使用exec函数族可以默认使用系统的环境变量,也可以传入指定的环境变量。这里,以“e”(Enviromen)结尾的两个函数execle、execve就可以在envp[]中传递当前进程所使用的环境变量进程 – execl / execlp
#include
<unistd.h>
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …);
#include <stdio.h>
#include <unistd.h>
int main()
{
/*调用execlp函数,相当于调用了“ps -ef”命令*/
if (execlp("ps", "ps", "-ef", NULL) < 0)
{
perror("execlp error!");
}
return 0;
}
exec函数族使用注意点在使用exec函数族时,一定要加上错误判断语句常见的错误原因有:找不到文件或路径,此时errno被设置为ENOENT数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT没有对应可执行文件的运行权限,此时errno被设置为EACCESS进程 – execv / execvp#include
<unistd.h>
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
执行ls命令,显示/etc目录下所有文件的详细信息
char
*arg[] = {“ls”, “-a”, “-l”, “/etc”, NULL};
if
(execv(“/bin/ls”, arg) < 0) {
perror(“execv”);
}
if
(execvp(“ls”, arg) < 0) {
perror(“execvp”);
}
进程 – system#include
<stdlib.h>
int system(const char *command);
定义:int system(const char * string);表头文件:#include<stdlib.h>说明:system()会调用fork()产生子进程, 由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令, 此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD信号会被暂时搁置, SIGINT和SIGQUIT 信号则会被忽略。返回值:如果system()在调用/bin/sh时失败则返回127, 其他失败原因返回-1。若参数string为空指针(NULL), 则返回非零值。如果system()调用成功则最后会返回执行shell命令后的返回值, 但是此返回值也有可能为system()调用/bin/sh失败所返回的127, 因此最好能再检查errno来确认执行成功。#include<stdlib.h>
int main(int argc, const char *argv[])
{
system("ls -al /etc/passwd /etc/shadow");
return 0;
}
}

我要回帖

更多关于 c语言程序设计教程第二版答案 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信