提交 b1ee423c 编写于 作者: H hypo

2-15

上级 e916287f
#define SH_TOK_BUFSIZE 64
#define SH_TOK_DELIM " \t\r\n\a"
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *shell_read_line();
char **shell_split_line(char * line);
int shell_execute(char **args);
void shell_loop(void){
char *line;
char **args;
int status;
do {
printf(">>");
line = shell_read_line();
args = shell_split_line(line);
status = shell_execute(args);
free(line);
free(args);
}while(status);
}
char *shell_read_line(){
char *line = NULL;
ssize_t bufsize = 0; // getline()function will help us allocate a buffer
getline(&line,&bufsize,stdin);
return line;
}
char **shell_split_line(char *line){
int bufsize = SH_TOK_BUFSIZE;
int position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char **token;
if(!tokens){
fprintf(stderr,"Mycshell:allocation error!\n");
exit(EXIT_FAILURE);
}
token = strtok(line,SH_TOK_DELIM);
while(token != NULL){
tokens[position] = token;
position++;
if(position >= bufsize){
bufsize += SH_TOK_BUFSIZE;
tokens = realloc(tokens,bufsize * sizeof(char*));
if(!tokens){
fprintf(stderr,"Mycshell:allocation error!\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL,SH_TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
}
int shell_launch(char **args){
pid_t pid,wpid;
int status;
pid = fork();
if(pid == 0){
if(execvp(args[0],args) == -1){
perror("mycshell");
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
//Error fork()
perror("mycshell");
} else {
do {
wpid = waitpid(pid,&status,WUNTRACED);
}while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}
/* Builtin Function part*/
int shell_help(char **args);
int shell_exit();
char *builtin_str[] = {"help","exit"};
int (*builtin_func[])(char **) = {&shell_help,&shell_exit};
int shell_num_builtins(){
return sizeof(builtin_str) / sizeof(char *);
}
int shell_help(char **args){
int i;
printf("This is J's cshell,\n");
printf("Type program names and arguments,then enter.\n");
printf("The following are built in:\n");
for(i = 0;i < shell_num_builtins();i++){
printf(" %s\n",builtin_str[i]);
}
printf("Please use the man command for information on other programs.\n");
return 1;
}
int shell_exit(char **args){
return 0;
}
int shell_execute(char **args){
int i;
if(args[0] == NULL){
//if input an empty command
return 1;
}
for(i = 0;i<shell_num_builtins();i++){
if(strcmp(args[0],builtin_str[i]) == 0){
return (*builtin_func[i])(args);
}
}
return shell_launch(args);
}
int main(int argc,char **agrv){
//Load config files;
shell_loop();
//Shutdown or Clean up;
}
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *shell_read_line();
char **shell_split_line(char * line);
int shell_execute(char **args);
void shell_loop(void){
char *line;
char **args;
int status;
do {
printf(">>");
line = shell_read_line();
args = shell_split_line(line);
status = shell_execute(args);
free(line);
free(args);
}while(status);
}
char *shell_read_line(){
char *line = NULL;
ssize_t bufsize = 0; // getline()function will help us allocate a buffer
getline(&line,&bufsize,stdin);
return line;
}
int main(int argc, char **argv[])
{
shell_loop();
}
\ No newline at end of file
......@@ -3,12 +3,12 @@
ps -aux |grep HelloWorld
```
3个进程的PIsssD分别是26608 26649 26689<br>
![image](./record/pic/2-1察看HelloWorld-gechar 的三个进程.jpg)
![image](./record/pic/2-1.jpg)
### 2-2 屏显 HelloWorld 可执行文件信息<br>
```bash
file HelloWorld
```
![image](./record/pic/2-2 屏显 HelloWorld 可执行文件信息.png)
![image](./record/pic/2-2.png)
x86-64 平台上的ELF 格式可执行文件。
一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
......@@ -21,9 +21,9 @@ Linux 系统中所有进程通过进程控制块PCB(struct task_struct)形
一个进程通过创建一个子进程则形成父子关系,如果创建多个子进程,那么这些新创建的
进程间属于兄弟关系<br>
### 2-3 pstree 输出
![image](./record/pic/2-3 pstree 输出.png)
![image](./record/pic/2-3.png)
### 2-4 查看会话、进程组和控制终端的例子
![image](./record/pic/2-4 查看会话、进程组和控制终端的例子.png)
![image](./record/pic/2-4.png)
### PPID(PPID,Parent PID) PID(进程ID) PGID(Process Group ID 进程组 ID号) SID(Session ID 会话ID) TTY TPGID(tty process group ID for the process group leader) STAT() UID TIME COMMAND<br>
STAT:D 无法中断的休眠状态(通常 IO 的进程);R 正在运行可中在队列中可过行的;S 处于休眠状态;T 停止或被追踪;W 进入内存交换(从内核2.6开始无效);X 死掉的进程(从来没见过);Z 僵尸进程;+ 位于后台的进程组<br>
“会话/进程组/线程组”几个概念呈现层级关系,Linux 系统中可以有多个会话(session),
......@@ -34,7 +34,7 @@ STAT:D 无法中断的休眠状态(通常 IO 的进程);R 正在运行可
chmod a+x shell-script
shell-script
```
![image](./record/pic/2-5 shell-script 脚本的执行.png)
![image](./record/pic/2-5.png)
第一行用于指出该脚本需要用/usr/bin/bash 来解
释执行,第二行shell 内部命令echo 用来显示,第三行HelloWorld 是外部命令(磁盘上的可执
行文件)。
......@@ -44,24 +44,39 @@ shell-script
```bash
ps -ef |grep HelloWorld-getchar
```
![image](./record/pic/2-6 通过ps 查找进程的PID.png)
![image](./record/pic/2-6.png)
### 2-7 fork-demo 的输出
![image](./record/pic/2-7 fork-demo 的输出.png)
![image](./record/pic/2-7.png)
fork 函数被成功调用后将按照父进程的样子复制出一个完全相同的子进程。父进程fork()
函数结束时的返回值是子进程的PID 编号。新创建的子进程则也是从fork()返回处开始执行,
但不同的是它获得的返回值是0。也就是说父子进程执行上几乎相同,<br>
* 唯一区别是子进程中返回0 值而父进程中返回子进程PID。<br>
* 如果fork()出错则只有父进程获得返回值-1 而子进程未能创建。<br>
### 2-8 fork-demo 的输出
![image](./record/pic/2-8 fork-demo 的pstree 输出.png)
![image](./record/pic/2-8.png)
### 2-9 fork-twice-demo 执行后的 输出
![image](./record/pic/2-9 fork-twice-demo 执行后的 输出.png)
![image](./record/pic/2-9.png)
### 孤儿进程和僵尸进程
(1) 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init 进程(进程号为1)所收养,并由init 进程对它们完成状态收集工作。
(2) 僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。
子进程结束后大部分资源都将直接回收,但是还将在PCB(struct task_struct 和内核堆栈)中记录一些退出时的状态等信息,这些信息供父进程检查后才能销毁回收。因此,僵尸进程因相应的数据没有父进程处理并回收,将会导致资源浪费,而孤儿则不会有这样的问题。
* 孤儿进程
![image](./record/pic/孤儿进程.png)
* 僵尸进程
![image](./record/pic/僵尸进程.png)
\ No newline at end of file
![image](./record/pic/僵尸进程.png)
### 2-10 fork-exec-demo 的执行结果
![image](./record/pic/2-10.png)
* 这里可以看到子进程通过execve()将自己变身为“/usr/bin/ls”,因此不再执行与父进程里的代——即后面的“printf("this printf()will not be executed, because …”是没有机会得到执行的。
* fork()和exec 函数族构成了创建新进程的完整操作,如果父子进程功能相同则只用fork(),如果父子进程不同则利用exec 函数族的来实现。
### 2-11 用ps –ajx 查看daemon-demo 守护进程
![image](./record/pic/2-11.png)
关闭daemon-demo运行终端后仍能找到daemon-demo进程,且PID为1
### 2-12 /etc/rsyslog.conf 中的内容
![image](./record/pic/2-12.png)
日志信息写入了/var/log/messages 文件中。
### 2-13 查看/var/log/messages
![image](./record/pic/2-13.png)
由于前后运行了多次,所以出现了3个。
### 2-14&2-15 pthread-demo 的输出及ps –aLf 的输出
![image](./record/pic/2-14&2-15.png)
两个线程公用一个PID号19392,但是LWP却不一样。
\ No newline at end of file
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int init_daemon(void)
{
int pid;
int i;
// 1)忽略一些控制终端发来的信号,信号的内容请参考其他文献
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP ,SIG_IGN);
// 2)在后台运行
if( pid=fork() )
{ // 父进程
exit(0); //结束父进程,子进程继续
}
else if(pid< 0)
{ // 出错
perror("fork");
exit(EXIT_FAILURE);
}
// 3)脱离控制终端、登录会话和进程组
setsid();
// 4)禁止进程重新打开控制终端
if( pid=fork() )
{ // 父进程
exit(0); // 结束第1 代子进程,第2 代子进程继续(第2 代子进程不再是会话组长)
}
else if(pid< 0)
{ // 出错
perror("fork");
exit(EXIT_FAILURE);
}
// 5)关闭打开的文件描述符
// NOFILE 为文件描述符最大个数,不同系统有不同限制,<sys/param.h> 的宏定义
for(i=0; i< NOFILE; ++i)
{
close(i);
}
// 6)改变当前工作目录
chdir("/tmp");
// 7)重设文件创建掩模
umask(0);
// 8)处理 SIGCHLD 信号
signal(SIGCHLD,SIG_IGN);
// 9) 输出日志
openlog("daemon-demo.log",LOG_PID,0);
syslog(LOG_INFO,"daemon-demo is running ...\n");
return 0;
}
int main(int argc, char *argv[])
{
init_daemon();
while(1);
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <unistd.h>
int main(int argc, char ** argv )
{
int i;
for(i=0;i<100;i++)
{
int pid = fork();
if(pid == -1 )
{
printf("error!\n");
}
else if( pid ==0 )
{
printf("This is the child process!\n");
sleep(10);
return 0;
}
else
{
printf("This is the parent process! child process id = %d\n", pid);
}
}
sleep(10);
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <unistd.h>
int main(int argc, char ** argv )
{
int pid = fork();
if(pid == -1 )
{
printf("error!\n");
}
else if( pid ==0 )
{
printf("This is the child process!\n");
char *argv[ ]={"ls", "-al", "/etc/passwd", NULL};
char *envp[ ]={"PATH=/usr/bin", NULL};
execve("/usr/bin/ls", argv, envp);
printf("this printf() will not be executed,because it will be replaced by /usr/bin/ls code!\n");
}
else
{
printf("This is the parent process! child process id = %d\n", pid);
getchar();
}
return 0;
}
\ No newline at end of file
文件模式从 100755 更改为 100644
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册