编程内容:

  1.完成  echo env export 命令

  2.完成前后台进程

  3.完成重定向

完整代码如下:

29.1 主函数、通用头文件和Makefile

29.1.1 主函数

  mshell_main.c

 #include <stdio.h>
#include <stdlib.h>
#include "mshell_handler.h" int main(int argc, char *argv[])
{
mshell_Handler();
}

29.1.2 通用文件

  mshell_common.h

 #ifndef __MSHELL_COMMON_H__
#define __MSHELL_COMMON_H__ #include <stdio.h>
#include <stdlib.h> typedef enum {
MSHELL_ERROR_NONE = ,
MSHELL_ERROR_PARAM ,
MSHELL_ERROR_MALLOC ,
MSHELL_ERROR_CALLOC ,
MSHELL_ERROR_PROG_CREATE,
MSHELL_ERROR_PROG_DESTROY,
MSHELL_ERROR_JOB_CREATE,
MSHELL_ERROR_JOB_DESTROY,
MSHELL_ERROR_JOB_PROGADD,
MSHELL_ERROR_CMD_NONECMD,
MSHELL_ERROR_REDIRECION_PARAM,
MSHELL_ERROR_REDIRECTION_CREATE,
MSHELL_ERROR_REDIRECTION_PARSE
}mshell_error_t; extern int mshell_args_Total(char **args);
extern void mshell_args_Free(char **args);
#endif

  mshell_common.c

 #include "mshell_common.h"

 /** 统计命令行参数的个数 */
int mshell_args_Total(char **args)
{
int i = ;
char *start = args[]; while(NULL != start) {
i++;
start = args[i];
} return i;
} void mshell_args_Free(char **args)
{
if(NULL == args){
return ;
} int i;
int len = sizeof(args);
for(i = ; i < len; i++) {
free(args[i]);
}
#if 0
while(NULL != args[i]){
free(args[i]);
i++;
}
#endif
free(args);
}

29.1.3 Makefile

 #PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
PROJECT_ROOT = $(shell pwd)
SRC_DIR = $(PROJECT_ROOT)/src
INCLUDE_DIR = $(PROJECT_ROOT)/include
OBJ_DIR = $(PROJECT_ROOT)/obj
BIN_DIR = $(PROJECT_ROOT)/bin # 找出 src 目录下的所有 .c 文件
C_SRCS = $(wildcard $(SRC_DIR)/*.c)
# 将所有的 src 下的 .c 文件替换为 .o 文件
C_OBJS = $(patsubst %c, %o, $(C_SRCS))
TARGET = mshell
SHARE_LIB = libmshell.a C_SRC_MAIN = mshell_main.c CC = gcc
CCFLAGS += fPIC
LDFLAGS += -shared -fPIC
ASFLAGS +=
ARFLAGS = -crs
LIBS_FLAGS = -L$(BIN_DIR) RM = rm -rf CFLAGS += -Wall -g -I$(INCLUDE_DIR)
INCDIR += -I$(INCLUDE_DIR) .PHONY: all clean test all: $(TARGET)
cp $(SHARE_LIB) $(BIN_DIR)
cp $(SRC_DIR)/*.o $(OBJ_DIR)/
$(RM) $(SHARE_LIB) $(SRC_DIR)/*.o $(TARGET): $(SHARE_LIB)
$(CC) $(C_SRC_MAIN) -o $(TARGET) $(CFLAGS) $(INCDIR) $(LIBS_FLAGS) -lmshell $(SHARE_LIB): $(C_OBJS)
$(AR) $(ARFLAGS) $(SHARE_LIB) $(C_OBJS)
cp $(SHARE_LIB) $(BIN_DIR) $(C_OBJS) : %.o:%.c
$(CC) -c $(CFLAGS) $(INCDIR) -o $@ $< clean:
$(RM) mshell
$(RM) $(SHARE_LIB)
$(RM) $(OBJ_DIR)/$(OBJS)/*.o
$(RM) $(SRC_DIR)/*.o

29.2 handler

  mshell_handler.c

 #include "mshell_handler.h"

 static mshell_error_t mshell_cmd_Parsed(mshell_job_t *job, char *line, mshell_process_Flag_t *process_flag)
{
/** Create args secondary pointer stored in program */
char **args_tmp = (char **)malloc(MSHELL_ARGS_SIZE * sizeof(char *));
if(NULL == args_tmp) {
return MSHELL_ERROR_MALLOC;
} /** Split the command line */
char *cmd = strtok(line, " "); /** The first parameter is the command itself */
args_tmp[] = (char *)calloc(strlen(cmd + ), sizeof(char));
if(NULL == args_tmp[]) {
return MSHELL_ERROR_MALLOC;
}
strcpy(args_tmp[], cmd); /** Start with the second parameter */
int i = ;
char *cmd_param;
mshell_redirection_t *redirections[MSHELL_REDIRECTION_NUMBER];
int redirection_num = ; while(NULL != (cmd_param = strtok(NULL, " "))) { /** 对命令行进行解析,判断是否为后台进程 */
int process_ret;
*process_flag = mshell_process_BackParse(cmd_param, &process_ret);
if( == process_ret) {
continue;
} /** 分析重定向 */
mshell_error_t redirection_ret;
redirections[redirection_num] =
mshell_redirection_Parse(redirections, redirection_num, cmd_param, &redirection_ret);
if(NULL != redirections[redirection_num] && MSHELL_ERROR_NONE == redirection_ret){
redirection_num++;
continue;
}
else if (NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECION_PARAM == redirection_ret) {
printf("need param\n");
continue;
}
else if(NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECTION_CREATE == redirection_ret)
{
perror("error create redirection");
return MSHELL_ERROR_REDIRECTION_CREATE;
} /** 分析命令 */
args_tmp[i] = (char *)calloc(strlen(cmd_param + ), sizeof(char));
if(NULL == args_tmp[i]) {
return MSHELL_ERROR_MALLOC;
}
strcpy(args_tmp[i], cmd_param);
i++;
}
args_tmp[i] = NULL; /** Store all command line parameters in program and free args_tmp*/
mshell_prog_t *prog = mshell_prog_Create(args_tmp);
if(NULL == prog) {
return MSHELL_ERROR_PROG_CREATE;
}
mshell_args_Free(args_tmp); /** Add redirection to job and free redirections*/
for(i = ; i < redirection_num; i++){
mshell_prog_RedirectionAdd(prog, redirections[i]);
}
mshell_redirections_Free(redirections, redirection_num); /** Add program to the job*/
if(MSHELL_ERROR_NONE != mshell_job_AddProg(job, prog)) {
return MSHELL_ERROR_JOB_PROGADD;
} #if 0
/** free args_tmp */
mshell_args_Free(args_tmp);
#endif
return ;
} static void mshell_cmd_ExcuProcess(mshell_job_t job, int order, mshell_process_Flag_t process_flag)
{
pid_t pid;
if((pid = fork()) < ) {
perror("fork error");
}
else if(pid == ) {
/** child process */
if(order == ) {
/** order = 0, 则为 minishell 当中启动的第一个子进程,设置其为组长进程 */
job.pgid = mshell_process_GroupGet(getpid(), getpid());
}
else {
/** order > 0, 则为启动的第二个进程,将其设置进程组的成员进程 */
job.pgid = mshell_process_GroupGet(getpid(), job.pgid);
}
mshell_process_GroupSet(process_flag, getpid());
/** 对便准输入、标准输出和追加进行重定向 */
mshell_prog_RedirectionExcu(job.progs[order]); /** 调用 exec 函数执行系统中的其他命令 */
if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job.progs[order].args))
exit();
}
else {
/** parent process */
if(order == ) {
job.pgid = mshell_process_GroupGet(pid, pid);
}
else {
job.pgid = mshell_process_GroupGet(pid, job.pgid);
}
mshell_process_GroupSet(process_flag, job.pgid); mshell_process_Wait(process_flag, job.pgid); #if 0
/** 等待指定的子进程结束, 阻塞版本,支持作业控制 */
if(waitpid(pid, NULL, WUNTRACED) < ) {
perror("waitpid error");
}
#endif
} } static mshell_error_t mshell_cmd_Excu(mshell_job_t *job, mshell_process_Flag_t process_flag)
{
int ret = MSHELL_ERROR_NONE;
int i;
for(i = ; i < job->progs_num; i++)
{
ret = mshell_Cmd_ExcuFun(job->progs[i].args);
if(MSHELL_ERROR_NONE == ret || MSHELL_ERROR_PARAM == ret) {
return MSHELL_ERROR_NONE;
} /** 执行其他命令 */
mshell_cmd_ExcuProcess(*job, i, process_flag);
#if 0
pid_t pid;
if((pid = fork()) < ) {
perror("fork error");
}
else if(pid == ) {
/** child process */
/** 调用 exec 函数执行系统中的其他命令 */
if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job->progs[i].args))
exit();
}
else {
/** parent process */
/** 等待指定的子进程结束, 阻塞版本,支持作业控制 */
if(waitpid(pid, NULL, WUNTRACED) < ) {
perror("waitpid error");
}
}
#endif
} return ;
} mshell_error_t mshell_Handler()
{
/**创建一个进程组,将 minishell 进程设置为进程组的组长 */
setpgid(getpid(), getpid()); char buffer[MSHELL_COMMAND_LEN];
memset(buffer, , MSHELL_COMMAND_LEN); ssize_t size = strlen(MSHELL_PROMPT) * sizeof(char);
write(STDOUT_FILENO, MSHELL_PROMPT, size); mshell_process_Flag_t process_flag; ///< 设置前台和后台进程的标志
ssize_t len;
while() { len = read(STDIN_FILENO, buffer, MSHELL_COMMAND_LEN); ///< 从命令行读取内容到 buffer
buffer[len - 1] = 0;
if(strlen(buffer) > ){
mshell_job_t *job = mshell_job_Create(buffer);
if(NULL == job) {
return MSHELL_ERROR_JOB_CREATE;
} mshell_cmd_Parsed(job, buffer, &process_flag);
mshell_cmd_Excu(job, process_flag);
//mshell_job_Destroy(job);
} write(STDOUT_FILENO, MSHELL_PROMPT, size);
memset(buffer, , MSHELL_COMMAND_LEN);
}
}

  mshell_handler.h

 #ifndef __MSHELL_HANDLER_H__
#define __MSHELL_HANDLER_H__ #include "mshell_common.h"
#include "mshell_process.h"
#include "mshell_cmd_fun.h"
#include "mshell_program.h"
#include "mshell_job.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <sys/wait.h> #define MSHELL_PROMPT "mshell =>"
#define MSHELL_COMMAND_LEN 256
#define MSHELL_ARGS_SIZE 100 mshell_error_t mshell_Handler(); #endif

29.3 作业

  mshell_job.h

 #ifndef __MSHELL_JOB_H__
#define __MSHELL_JOB_H__ #include "mshell_common.h"
#include "mshell_program.h"
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h> /** job struct, A job contains several programs to execute */
typedef struct {
char *cmd; ///< String commands to be executed
pid_t pgid; ///< 进程组的 ID
int progs_num; ///< Number of programs to execute
mshell_prog_t *progs; ///< Point to several programs to be executed
}mshell_job_t; extern mshell_job_t* mshell_job_Create(char *cmd);
extern void mshell_job_Destroy(mshell_job_t *job);
extern mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog);
#endif

  mshell_job.c

 #include "mshell_common.h"
#include "mshell_program.h"
#include "mshell_job.h" mshell_job_t* mshell_job_Create(char *cmd)
{
mshell_job_t *job = (mshell_job_t *)malloc(sizeof(mshell_job_t));
if(NULL == job)
{
return NULL;
} job->cmd = (char *)malloc(sizeof(char) * strlen(cmd));
if(NULL == job->cmd)
{
return NULL;
} strcpy(job->cmd, cmd);
job->progs_num = ;
job->progs = NULL; return job;
}
void mshell_job_Destroy(mshell_job_t *job)
{
if(NULL == job)
{
return ;
}
free(job->progs);
free(job->cmd);
free(job);
} mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog)
{
mshell_prog_t *prog_tmp = (mshell_prog_t *)malloc(sizeof(mshell_prog_t) * (job->progs_num + ));//1 为NULL的初始化
if(NULL == prog_tmp) {
return MSHELL_ERROR_MALLOC;
} memcpy(prog_tmp, job->progs, job->progs_num * sizeof(mshell_prog_t));
prog_tmp[job->progs_num++] = *prog;
free(job->progs);
job->progs = prog_tmp; return MSHELL_ERROR_NONE;
}

29.4 程序

  mshell_program.h

 #ifndef __MSHELL_PROGRAM_H__
#define __MSHELL_PROGRAM_H__ #include "mshell_common.h"
#include "mshell_redirection.h"
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h> /** program struct */
typedef struct {
/**
* Command-line parameters obtained from the terminal
* Char*argv[] parameter corresponding to the main function
*/
char **args;
pid_t pid; ///< 进程 ID
int redirection_num; ///< 重定向的数量
mshell_redirection_t *redirecitons; ///< 重定向结构体数组
}mshell_prog_t; extern mshell_prog_t* mshell_prog_Create(char **args);
extern void mshell_prog_Destroy(mshell_prog_t *prog);
extern void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection);
extern void mshell_prog_RedirectionExcu(mshell_prog_t prog);
#endif

  mshell_program.c

 #include "mshell_program.h"

 /**
* Init program's pointer array
*/
static mshell_prog_t * mshell_prog_ArgsInit(mshell_prog_t *prog, char **args, int counter)
{
int i; for(i = ; i < counter; i++) {
int len = strlen(args[i]);
prog->args[i] = (char *)malloc(len);
if(NULL == prog->args[i]){
return NULL;
} strcpy(prog->args[i], args[i]);
}
return prog;
} mshell_prog_t * mshell_prog_Create(char **args)
{
mshell_prog_t *prog = (mshell_prog_t *)malloc(sizeof(mshell_prog_t));
if(NULL == prog){
return NULL;
} /** Init program's redirection */
prog->redirection_num = ;
prog->redirecitons = NULL; /** Init program's pointer array */
int args_num = mshell_args_Total(args);
prog->args = (char **)calloc(args_num + , sizeof(char *));
prog = mshell_prog_ArgsInit(prog, args, args_num);
return prog;
} void mshell_prog_Destroy(mshell_prog_t *prog)
{
if(NULL == prog) {
return ;
} mshell_args_Free(prog->args);
free(prog->redirecitons);
free(prog);
} void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection)
{
mshell_redirection_t *redirections = (mshell_redirection_t *)calloc(prog->redirection_num + , sizeof(mshell_redirection_t));
if(NULL == redirections){
return;
} if(NULL != prog->redirecitons) {
memcpy(redirections, prog->redirecitons, prog->redirection_num * sizeof(redirections));
free(redirections);
} prog->redirecitons = redirections;
memcpy(&prog->redirecitons[prog->redirection_num], redirection, sizeof(mshell_redirection_t));
prog->redirection_num += ;
} void mshell_prog_RedirectionExcu(mshell_prog_t prog)
{
int i;
for(i = ; i < prog.redirection_num; i++) {
mshell_redirection_Excu(prog.redirecitons[i]);
}
}

29.5 命令

  mshell_cmd_fun.h

 #ifndef __MSHELL_CMD_FUN_H__
#define __MSHELL_CMD_FUN_H__ #include "mshell_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> #define MSHELL_CMD_CD "cd"
#define MSHELL_CMD_PWD "pwd"
#define MSHELL_CMD_EXIT "exit"
#define MSHELL_CMD_ENV "env"
#define MSHELL_CMD_ECHO "echo"
#define MSHELL_CMD_EXPORT "export" typedef void (* mshell_cmd_Fun)(char *args);
typedef struct {
char *cmd;
mshell_cmd_Fun callback;
}mshell_funs_t; mshell_error_t mshell_Cmd_ExcuFun(char **args);
mshell_error_t mshell_Cmd_ExcuOther(char **args);
#endif

  mshell_cmd_fun.c

 #include "mshell_cmd_fun.h"

 extern char** environ;

 static void mshell_cmd_Cd(char *args)
{
if(chdir(args) < ) {
perror("cd error");
}
} static void mshell_cmd_Pwd(char *args)
{
char buffer[];
memset(buffer, , sizeof(buffer));
if(getcwd(buffer, sizeof(buffer)) == NULL){
perror("pwd error");
} printf("%s\n", buffer);
} static void mshell_cmd_Exit(char *args)
{
exit();
} static void mshell_mcd_Env(char *args)
{
int i = ;
char *env = NULL; while(NULL != (env = environ[i])) {
printf("%s\n", env);
i++;
}
} static void mshell_mcd_Echo(char *args)
{
char *arg_tmp = args;
if(NULL == arg_tmp) {
fprintf(stderr, "echo: invalid argument\n");
return;
} if('$' == arg_tmp[]) {
char *env_tmp = getenv(arg_tmp + );
printf("%s\n", env_tmp);
}
else {
printf("%s\n", arg_tmp);
}
} static void mshell_mcd_Export(char *args)
{
if(NULL == args) {
fprintf(stderr, "export: invalid argument\n");
return;
} putenv(args);
} static mshell_funs_t mshell_table_fun[] = {
/** cmd func */
{MSHELL_CMD_CD , mshell_cmd_Cd},
{MSHELL_CMD_PWD , mshell_cmd_Pwd},
{MSHELL_CMD_EXIT, mshell_cmd_Exit},
{MSHELL_CMD_ENV , mshell_mcd_Env},
{MSHELL_CMD_ECHO, mshell_mcd_Echo},
{MSHELL_CMD_EXPORT, mshell_mcd_Export},
}; mshell_error_t mshell_Cmd_ExcuFun(char **args)
{
if(NULL == args) {
return MSHELL_ERROR_PARAM;
}
int len = sizeof(mshell_table_fun) / sizeof(mshell_funs_t);
int i;
for(i = ; i < len; i++) {
if(!strcmp(args[], mshell_table_fun[i].cmd)){
mshell_table_fun[i].callback(args[]);
return MSHELL_ERROR_NONE;
}
} return MSHELL_ERROR_CMD_NONECMD;
} mshell_error_t mshell_Cmd_ExcuOther(char **args)
{
/** excu 函数成功执行不返回,出错会返回 -1 */
if(execvp(args[], args) < ) {
perror("execvp error");
/** 这里退出后,让后面的程序继续执行 */
return MSHELL_ERROR_CMD_NONECMD;
} return MSHELL_ERROR_NONE;
}

29.6 重定向

  mshell_redirection.h

 #ifndef __MSHELL_REDIRECTION_H__
#define __MSHELL_REDIRECTION_H__ #include "mshell_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h> #define MSHELL_REDIRECTION_NUMBER 5 #define MSHELL_REDIRECTION_READ "<"
#define MSHELL_REDIRECTION_WRITE ">"
#define MSHELL_REDIRECTION_APPEND ">>" typedef enum {
mshell_Redirection_Read,
mshell_Redirection_Write,
mshell_Redirection_Append
}mshell_redirection_type_t; typedef struct {
mshell_redirection_type_t type;
int fd;
}mshell_redirection_t; typedef mshell_redirection_t* (* mshell_redirection_fun)(char *file);
typedef struct {
char *type;
mshell_redirection_fun callback;
}mshell_table_redirection_t; typedef void (* mshell_redirection_ExcuFun)(int fd);
typedef struct {
mshell_redirection_type_t type;
mshell_redirection_ExcuFun callback;
}mshell_Table_redirectionExcu_t; extern mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type);
extern void mshell_redirection_Destroy(mshell_redirection_t *redirection);
extern mshell_redirection_t *mshell_redirection_Parse(
mshell_redirection_t **redirection,
int num,
char *args,
mshell_error_t *error);
extern void mshell_redirections_Free(mshell_redirection_t **redirections, int num);
extern void mshell_redirection_Excu(mshell_redirection_t redirection);
#endif

  mshell_redirection.c

 #include "mshell_redirection.h"

 mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type)
{
mshell_redirection_t *redirection = (mshell_redirection_t *)calloc(, sizeof(mshell_redirection_t));
if(NULL == redirection){
return NULL;
} redirection->fd = fd;
redirection->type = type;
return redirection;
} void mshell_redirection_Destroy(mshell_redirection_t *redirection)
{
if(NULL == redirection) {
return;
}
free(redirection);
} static mshell_redirection_t *mshell_redirection_Read(char *file)
{
int fd = open(file, O_RDONLY);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Read);
return redirection;
} static mshell_redirection_t *mshell_redirection_Write(char *file)
{
int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Write);
return redirection;
} static mshell_redirection_t *mshell_redirection_Append(char *file)
{
int fd = open(file, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Append);
return redirection;
} static mshell_table_redirection_t mshell_redirection_table[] = {
/** args func */
{MSHELL_REDIRECTION_READ, mshell_redirection_Read},
{MSHELL_REDIRECTION_WRITE, mshell_redirection_Write},
{MSHELL_REDIRECTION_APPEND, mshell_redirection_Append},
}; mshell_redirection_t *mshell_redirection_Parse(
mshell_redirection_t **redirection,
int num,
char *args,
mshell_error_t *error)
{
int len = sizeof(mshell_redirection_table) / sizeof(mshell_table_redirection_t);
int i; for(i = ; i < len; i++) {
if(!strcmp(args, mshell_redirection_table[i].type)) {
char *file = strtok(NULL, " ");
if(NULL == file) {
*error = MSHELL_ERROR_REDIRECION_PARAM;
return NULL;
}
else
{
redirection[num] = mshell_redirection_table[i].callback(file);
if(NULL == redirection[num]){
*error = MSHELL_ERROR_REDIRECTION_CREATE;
return NULL;
}
else {
*error = MSHELL_ERROR_NONE;
return redirection[num];
}
}
}
} return NULL;
} void mshell_redirections_Free(mshell_redirection_t **redirections, int num)
{
if(NULL == redirections){
return;
}
int i;
for(i = ; i < num; i++) {
mshell_redirection_Destroy(redirections[i]);
} } static void mshell_redirection_ExcuRead(int fd)
{
if(dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
perror("dup2");
}
} static void mshell_redirection_ExcuWrite(int fd)
{
if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
}
} static void mshell_redirection_ExcuAppend(int fd)
{
if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
}
} static mshell_Table_redirectionExcu_t mshell_redirection_ExcuTable[] = {
/** type func */
{mshell_Redirection_Read, mshell_redirection_ExcuRead},
{mshell_Redirection_Write, mshell_redirection_ExcuWrite},
{mshell_Redirection_Append, mshell_redirection_ExcuAppend},
}; /** 对标准输入、标准输出和追加进行重定向 */
void mshell_redirection_Excu(mshell_redirection_t redirection)
{
int i;
int len = sizeof(mshell_redirection_ExcuTable) / sizeof(mshell_Table_redirectionExcu_t);
for(i = ; i < len; i++) {
if(redirection.type == mshell_redirection_ExcuTable[i].type) {
mshell_redirection_ExcuTable[i].callback(redirection.fd);
}
}
}

29.7 进程

  mshell_process.h

 #ifndef __MSHELL_PROCESS_H__
#define __MSHELL_PROCESS_H__ #include "mshell_common.h"
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef enum {
MSHELL_PROCESS_FORE = ,
MSHELL_PROCESS_BACK =
}mshell_process_Flag_t; /** 解析 & 符号,设置进程组标志为前台或后台进程标指 */
extern mshell_process_Flag_t mshell_process_BackParse(char *args, int *error);
extern pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid);
extern void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid);
extern void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid); #endif /* INCLUDE_MSHELL_PROCESS_H_ */

  mshell_process.c

 /*
* mshell_process.c
*
* Created on: 2018年12月26日
* Author: homework
* brief:
* 启动的 minishell 本身就是一个进程,在一个进程组当中,
* 在 minishell 中启动的若干个进程中,其中就有一个父进程,也可能还有其他子进程
* 在此基础上,再做一个进程组
* 把 minishell 启动起来后,做为一个进程组,minishell 为组长进程
* 在 minishell 上启动多个进程,将这些进程作为一个进程组
* 1. 把 minishell 单独设置为一个进程组
* 2. 把在 minishell 中启动的进程设置为一个进程组
* 2.1 把在 minishell 中启动的第一个进程作为进程组的组长
* 2.2 后面创建的进程放置进此进程组当中
*/ #include "mshell_process.h" /** 解析 & 符号,设置进程组标志为前台或后台进程标指 */
mshell_process_Flag_t mshell_process_BackParse(char *args, int *error)
{
mshell_process_Flag_t process_flag = MSHELL_PROCESS_FORE;
if(!strcmp(args, "&")){
process_flag = MSHELL_PROCESS_BACK;
*error = ;
return process_flag;
} *error = -;
return process_flag;
} /** 创建进程组并获取进程组 ID */
pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid)
{
if(setpgid(pid, group_pid) < ) {
perror("setpgid error");
} return group_pid;
} /** 设置前台进程组 */
void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid)
{
if(process_flag == MSHELL_PROCESS_FORE) {
tcsetpgrp(, getpgid(pid));
}
} void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid)
{
if(process_flag == MSHELL_PROCESS_FORE) {
waitpid(-pgid, NULL, WUNTRACED);
} if(process_flag == MSHELL_PROCESS_BACK) {
waitpid(-pgid, NULL, WNOHANG);
}
}

二十九、Linux 进程与信号——minishell(2)的更多相关文章

  1. 二十、Linux 进程与信号---非局部跳转

    20.1 setjmp 和 longjmp 函数 20.1.1 函数介绍 #include <setjmp.h> int setjmp(jmp_buf env); 函数功能:设置非局部跳转 ...

  2. 三十、Linux 进程与信号——信号的概念及 signal 函数

    30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...

  3. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  4. 二十一、Linux 进程与信号---进程查看和进程状态、进程调度和进程状态变化、进程标识

    21.1 进程查看和进程状态 21.1.1 ps 指令 ps 指令通常可以查看到进程的 ID.进程的用户 ID.进程状态和进程的 Command ps:查看当前用户启动的进程 ps -ef:详细查看后 ...

  5. 二十一、Linux 进程与信号---进程资源限制

    21.1 进程资源限制 在操作系统中,我们能够通过函数getrlimit().setrlimit()分别获得.设置每个进程能够创建的各种系统资源的限制使用量. 21.1.1 函数 #include & ...

  6. 二十七、Linux 进程与信号---进程组和组长进程

    27.1 进程组 27.1.1 进程组介绍 进程组为一个或多个进程的集合 进程组可以接受同一终端的各种信号,同一个信号发送进程组等于发送给组中的所有进程 每个进程组有唯一的进程组 ID 进程组的消亡要 ...

  7. [转帖]十二 个经典 Linux 进程管理命令介绍

    https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看.   随笔- 109  ...

  8. Web 开发人员和设计师必读文章推荐【系列二十九】

    <Web 前端开发精华文章推荐>2014年第8期(总第29期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  9. 第三百二十九节,web爬虫讲解2—urllib库爬虫—ip代理—用户代理和ip代理结合应用

    第三百二十九节,web爬虫讲解2—urllib库爬虫—ip代理 使用IP代理 ProxyHandler()格式化IP,第一个参数,请求目标可能是http或者https,对应设置build_opener ...

随机推荐

  1. HR_Array Manipulation

    第一版有7个时间超限,优化成了第二版: 1: #!/bin/python3 import math import os import random import re import sys # Com ...

  2. 2018蓝桥杯 省赛D题(测试次数)

    x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机.各大厂商也就纷纷推出各种耐摔型手机.x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通.x星球 ...

  3. Kafka史上最详细原理总结

    https://blog.csdn.net/ychenfeng/article/details/74980531 Kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(pa ...

  4. 用宏定义代替printf函数

    来自:http://blog.csdn.net/yannanxiu/article/details/52506451 #define _DEBUG_ 1 #if _DEBUG_ #define PR( ...

  5. 团体程序设计天梯赛(CCCC) L3009 长城 方法证明

    团体程序设计天梯赛代码.体现代码技巧,比赛技巧.  https://github.com/congmingyige/cccc_code

  6. Xml二(解析思想)、

    XML解析: * 解析xml可以做: * 如果xml作为配置文件:读取 * 如果xml作为传输文件:写,读 * xml解析思想: * DOM:将文档加载进内存,形成一颗dom树(document对象) ...

  7. 高级组件——进度条 JProgressBar

    JProgressBar pro=new JProgressBar(); pro.setIndeterminate(boolean); 设置不确定性        false,确定的进度条(显示进度, ...

  8. IO 多路复用介绍

    IO多路复用 概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系 ...

  9. Luogu P4011 孤岛营救问题

    题目链接 \(Click\) \(Here\) 注意坑点:一个地方可以有多把钥匙. 被卡了一会,调出来发现忘了取出来实际的数字,直接把二进制位或上去了\(TwT\),其他的就是套路的分层图最短路.不算 ...

  10. 微信小程序:多张图片上传

    最近在写小程序的相册,需要多张图片的上传.因为小程序不支持数组的多张图片同时上传,然后根据自己的需求+借鉴网上各位大神的案例,总算搞定.分享下,不足之处,多多指教哦 页面wxml: <form ...