C语言实现shell

涉及到的相关函数

获取用户名 :

uid_t getuid(void);

struct passwd *getpwuid(uid_t uid);

//getpwuid 返回一个结构体指针,可以用来获取下列结构
struct passwd {
   
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* user information */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };

获取当前工作目录 :

char *getcwd(char *buf, size_t size);

getcwd可以将当前工作的绝对路径填充进buf指向的空间;
大小不超过size; 失败返回NULL指针, 并设置errno;

切换工作路径 :

int chdir(const char *path);

改变当前进程的工作路径,成功返回 0, 失败返回-1;
并设置errno;
The current working directory is the starting point for interpreting relative pathnames (those not starting with '/').

切换路径后修改命令行的提示

void swim_dir() {
   
    if (chdir(vec[1]) < 0){
   
        perror("chdir()");
        return;
    }
    has_ch_dir = 1;
}

重定位功能相关函数

复制文件描述符

int dup(int oldfd);
int dup2(int oldfd, int newfd);
//dup用未使用的最小文件file descriptor 复制当前oldfd,并返回;
//dup2将之前打开的newfd用来复制oldfd, 它会前关闭之前的newfd再
//指向oldfd,如果oldfd是无效的,那么它啥事也不做;
失败返回:-1,并设置errno;

啥是文件描述符 ?

文件描述符是数组下标, 数组里存放了打开文件结构体的指针, 指向的结构体里又有指向inode的指针; 该数组存在在每个进程空间里, 系统会默认打开默认stream: stdin/stdout/stderr;

在这里插入图片描述

fork() 复制产生子进程

fork可以产生一个新进程,通过duplicate 当前进程

fork后父子进程的区别:

  1. fork的返回值不一样, pid不一样, ppid不一样;
  2. 未决信号和文件锁不继承
  3. 资源利用量清零;

注意 : fork()进行写时复制(谁改变原内容, 谁复制)

在这里插入图片描述

pipe() 实现IPC机制
    调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信, 有一个读端和写端, 通过 filedes参数传给用户程序的两个文件描述符, filedes[0]指向管道的读端, filedes[1]指向管道的写端;
 /* On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64; see NOTES */
struct fd_pair {
   
    long fd[2];
};
struct fd_pair pipe();

/* On all other architectures */
int pipe(int pipefd[2]);

在这里插入图片描述

管道用法的栗子

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
       
    pid_t pid;
    int fd[2];
    
    if (pipe(fd) < 0) {
   
        perror("pipe()");
        exit(1);
    } 
    
    if ((pid = fork()) < 0){
   
        perror("fork()");
        exit(1);
    }
    int n;
    char buf[20];
    if (pid > 0) {
   
        close(fd[0]);
        write(fd[1], "hello pipe\n", 11);
        wait(NULL);
    }
    else{
   
        close(fd[1]);
        sleep(1);
        n = read(fd[0], buf, 20);
        write(1, buf, n);
    }    

	return 0;
}

命令的执行相关函数

当进程调用一种exec函数时, 改函数的用户空间代码和数据完全被新程序替代, 从新程序的启动例程开始执行

//exec函数族
int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);
int execlp(const char *file, const char *arg, ... /*
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值