shell
shell
What is a shell?
shell is like a matchmaker in linux, we have to shell command, shell to tell the system what we need to do, for us to pull strings, call the operating system available to achieve our interface, shell provides communication between you and the operating system the way.
linux kernel (kernel), we can not directly touched, but through the shell, shell is the outermost layer of the operating system. the interaction between the shell and manage your operating system: waiting for your input, to the operating system interprets your input, processing and output of a variety of operating systems results, explain it to you.
The following diagram circled in red to show something that is in the form of a shell in front of us.
Write your own simple shell preparations
fork () function creates the child process
fork function running program is divided into two (almost) exactly the same process, each process started a thread begins execution of code from the same location. These two threads in the process to continue, as if two users simultaneously launched two copies of the application.
fork()
For example please move on my blog process
wait () function
Prototype:
pid_t wait(int* status);
pid_t waitpid(pid_t pid, int* status, int options);
wait()
: Wait for any one child process exits, if no child process exits, the blocking has been waiting for
waitpid()
: the specified child process can wait, can wait for any one child process exits, can be set to a non-blocking wait for
blocking: In order to complete a function to initiate a function call If this function is not complete functions have been suspended to wait before returning to complete
a non-blocking: in order to complete a function to initiate a function call, if we do not have the conditions to complete, then immediately return without waiting
options:
- WNOHANG If no child process exits, then immediately return an error if there is recovery resources
- WUNTRACED if the child enters the suspend state, immediately returned, but the end state of the child process is not to be ignored
Acquisition process exit status code: Exit Reason parameter is stored in the sub-process and wait in the exit code, but only the parameters of the lower 16 bits used to store two bytes of information
in which the low 16 bits, the upper eight bits the exit code is stored, the program has finished running, quit will have low storage 7 is an abnormal situation, the eight core dump is a sign
how to get
WIFEXITED and generally used in conjunction with WEXITSTATUS
WIFEXTED(status) 这个宏用来获取是否正常退出,正常退出获得true
WEXITSTATUS(status) 该宏只可在WIFEXITED为true时使用,获取正常退出的状态码
WIFSIGNALED and WTERMSIG
WIFSIGNALED(status) 这个宏用来获取是否异常退出,异常退出获得true
WTERMSIG(status) 该宏只可在WIFSIGNALED为true时使用,获取异常退出的状态码
Replace the code in the child class function --exec
exec family of functions is the role of program replacement if the replacement is successful, the exec source code will not run unless an error, which means that if you write printf after exec, will not have any output
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* 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[]);
The six function names and parameters are similar, using them is almost the same, in which the 'l' (list) represents the parameter list, 'v' (vector) represents a parameter array, 'p' (path) indicate automatically searches the environment variables PATH, 'e' (env) expressed the need to maintain their own environment variables:
- Parameter
const char* path
, you need to tell the operating system, program files full path
parameters areconst char* file
not required to tell the path, only the file name will automatically find the path to the next PATH - execle and execve not inherit environment variables from the parent process, organized by the user environment variables
other functions (functions that do not end e) inherited from the parent process environment variables - three functions execl more in line with our usual habits, in order to
ls -l
, for example, when using the inputint execlp("ls", "ls", "-l");
three functions execv is in the form of an array of pointers with
Carding process execution of shell
- Get input terminal
- Parse input
- Create a child process, child processes replacement program
- The parent process waits for the child process has finished running, corpses
Code
Thank big brother Sun Yu Mo pointed out bug, the code has been modified to learn Gangster
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int argc = 0;
char* argv[32] = {NULL};
int div_commond(char* buf)
{
if (buf == NULL)
return -1;
argc = 0;
char* front = buf;
char* back = buf;
//不断分割命令成指针数组
while (1)
{
while (*front == ' ')
front++;
if (*front == '\0')
break;
back = front;
while (*back != ' ' && *back != '\0')
back++;
if (*back == '\0')
{
argv[argc++] = front;
break;
}
*back = '\0';
argv[argc++] = front;
front = back + 1;
}
argv[argc++] = NULL;
if (argc == 1)
return -1;
return 0;
}
int exec_cmd()
{
int pid = fork();
if (pid < 0)
{
perror("fork failed");
return -1;
}
else if (pid == 0)
{
//替换进程
execvp(argv[0], argv);
exit(0);
}
else
{
//wait用法,等待子进程退出,退出后一个状态码会存入statu
//用WIFEXITED这个宏来获取退出值是否是正常退出
int status;
wait(&status);
if (WIFEXITED(status) == 1)
printf("%s\n", strerror(WEXITSTATUS(status)));
}
return 0;
}
int main()
{
char buf[1024];
while (1)
{
memset(buf, 0x00, 1024);
printf("------shell>>>>>>");
//读取到\n为止,删除缓冲区数据
scanf("%[^\n]%*c", buf);
if (div_commond(buf) != 0)
{
char black_hall[100];
fgets(black_hall, 100, stdin);
printf("wrong commond\n");
continue;
}
exec_cmd();
}
return 0;
}