内置命令不可以通过fork+exec方式实现,所以不能用bash
cd
改变当前工作路径
exit
mybash.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/wait.h>
6 #include<pwd.h>
7
8 #define ARG_MAX 10
9 char* get_cmd(char buff[],char* myargv[])//解析命令
10 {
11 if(buff==NULL||myargv==NULL)
12 {
13 return NULL;
14 }
15
16 int i=0;//数组下标
17 char*s=strtok(buff," ");
18 while(s!=NULL)
19 {
20 myargv[i++]=s;
21 s=strtok(NULL," ");
22 }
23 return myargv[0];
24 }
25 void run_cmd(char* path,char* myargv[])
26 {
27 if(path==NULL)
28 {
29 return;
30 }
31 pid_t pid=fork();
32 if(pid==-1)
33 {
34 return;
35 }
36 if(pid==0)
37 {
38 execvp(path,myargv);
39 perror("cmd err");//执行失败,退出子进程
40 exit(0);
41 }
42 wait(NULL);
43 }
44 void printf_info()//打印提示符
45 {
46 char* user_str="$";
47 char* source_info="mybash1.0 >>";
48 int uid = getuid();
49 if(uid == 0)
50 {
51 user_str = "#";
52 }
53 struct passwd* ptr=getpwuid(uid);
54 if(ptr==NULL)
55 {
56 printf("%s",source_info);
57 fflush(stdout);
58 return;
59 }
60 char hostname[128]={0};
61 if(gethostname(hostname,128)==-1)
62 {
63 printf("%s",source_info);
64 fflush(stdout);
65 return;
66 }
67
68 char pwd_str[256]={0};
69 if(getcwd(pwd_str,256)==NULL)
70 {
71
72 printf("%s",source_info);
73 fflush(stdout);
74 return;
75 }
76
77 printf("\033[1;32m%s@%s\033[0m:\033[1;34m%s\033[0m%s ",ptr->pw_name,hostname,pwd_str,user_str);
78 fflush(stdout);
79 }
80 int main()
81 {
82 while(1)
83 {
84 //printf("maria@ubantu: ~]$");
85 //fflush(stdout);
86
87 char buff[128]={0};
88 printf_info();
89 fgets(buff,128,stdin);
90 buff[strlen(buff)-1]=0;
91 char* myargv[ARG_MAX]={0};
92 char* cmd=get_cmd(buff,myargv);
93 if(cmd==NULL)
94 {
95 continue;
96 }
97 else if(strcmp(cmd,"exit")==0)
98 {
99 break;
100 }
101 else if(strcmp(cmd,"cd")==0)
102 {
103 if(myargv[1]==NULL)
104 {
105 continue;
106 }
107
108 if(chdir(myargv[1])==-1)
109 {
110 perror("cd err:");
111 }
112 }
113 else
114 {
115 run_cmd(cmd,myargv);
116 }
117 }
118 exit(0);
119 }
运行结果
pwd.c
运行结果
ls.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<dirent.h>
5 #include<string.h>
6 #include<sys/stat.h>
7 int main(int argc,char* argv[])
8 {
9 char curr_dir[256]={0};
10 if(argc==2)
11 {
12 strcpy(curr_dir,argv[1]);
13 }
14 else
15 {
16 if(getcwd(curr_dir,256)==NULL)
17 {
18 printf("ls err\n");
19 exit(1);
20 }
21 }
22
23 DIR* p=opendir(curr_dir);//传入位置参数
24 struct dirent* s=NULL;//从文件目录中读取文件属性
25 struct stat st;
26 while((s=readdir(p))!=NULL)//非隐藏文件
27 {
28 if(strncmp(s->d_name,".",1)==0)
29 {
30 continue;
31 }
32 if(lstat(s->d_name,&st)==-1)//文件属性,类型,大小,权限,属主
33 {
34 printf("%s ",s->d_name);
35 continue;
36 }
37 if(S_ISDIR(st.st_mode))//判断是否为目录文件
38 {
39 printf("\033[1;32m%s\033[0m ",s->d_name);
40 }
41 else if(S_ISFIFO(st.st_mode))//判断是否为管道文件
42 {
43 printf("\033[40;33m%s\033[0m ",s->d_name);
44 }
45 else//普通文件
46 {
47 //具有执行权限-绿,有执行权限-黑色
48 if(st.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))
49 {
50 printf("\033[1;32m%s\033[0m ",s->d_name);
51 }
52 else
53 {
54 printf("%s:%ld ",s->d_name,st.st_size);
55 }
56 }
57 }
58 printf("\n");
59
60 closedir(p);
61 exit(0);
62 }
运行结果
mybah.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/wait.h>
6 #include<pwd.h>
7
8
9 #define PATH_BIN "/home/maria/c215/20220523/mybin/"
10 #define ARG_MAX 10
11 char* get_cmd(char buff[],char* myargv[])//解析命令
12 {
13 if(buff==NULL||myargv==NULL)
14 {
15 return NULL;
16 }
17
18 int i=0;//数组下标
19 char*s=strtok(buff," ");
20 while(s!=NULL)
21 {
22 myargv[i++]=s;
23 s=strtok(NULL," ");
24 }
25 return myargv[0];
26 }
27 void run_cmd(char* path,char* myargv[])
28 {
29 if(path==NULL)
30 {
31 return;
32 }
33 pid_t pid=fork();
34 if(pid==-1)
35 {
36 return;
37 }
38 if(pid==0)
39 {
40 char path_name[128]={0};
41 if(strncmp(path,"/",1)==0||strncmp(path,"./",2)==0)
42 {
43 strcpy(path_name,path);
44 }
45 else
46 {
47 strcpy(path_name,PATH_BIN);
48 strcat(path_name,path);
49 }
50 execv(path_name,myargv);
51 //execvp(path,myargv);
52 perror("cmd err");//执行失败,退出子进程
53 exit(0);
54 }
55 wait(NULL);
56 }
57 void printf_info()//打印提示符
58 {
59 char* user_str="$";
60 char* source_info="mybash1.0 >>";
61 int uid = getuid();
62 if(uid == 0)
63 {
64 user_str = "#";
65 }
66 struct passwd* ptr=getpwuid(uid);
67 if(ptr==NULL)
68 {
69 printf("%s",source_info);
70 fflush(stdout);
71 return;
72 }
73 char hostname[128]={0};
74 if(gethostname(hostname,128)==-1)
75 {
76 printf("%s",source_info);
77 fflush(stdout);
78 return;
79 }
80
81 char pwd_str[256]={0};
82 if(getcwd(pwd_str,256)==NULL)
83 {
84
85 printf("%s",source_info);
86 fflush(stdout);
87 return;
88 }
89
90 printf("\033[1;32m%s@%s\033[0m:\033[1;34m%s\033[0m%s ",ptr->pw_name,hostname,pwd_str,user_str);
91 fflush(stdout);
92 }
93 int main()
94 {
95 while(1)
96 {
97 //printf("maria@ubantu: ~]$");
98 //fflush(stdout);
99
100 char buff[128]={0};
101 printf_info();
102 fgets(buff,128,stdin);
103 buff[strlen(buff)-1]=0;
104 char* myargv[ARG_MAX]={0};
105 char* cmd=get_cmd(buff,myargv);
106 if(cmd==NULL)
107 {
108 continue;
109 }
110 else if(strcmp(cmd,"exit")==0)
111 {
112 break;
113 }
114 else if(strcmp(cmd,"cd")==0)
115 {
116 if(myargv[1]==NULL)
117 {
118 continue;
119 }
120
121 if(chdir(myargv[1])==-1)
122 {
123 perror("cd err:");
124 }
125 }
126 else
127 {
128 run_cmd(cmd,myargv);
129 }
130 }
131 exit(0);
132 }
运行结果(拼接路径)
cp
如何复制文件夹到新的文件夹内?
首先在要复制到的新文件夹内创建一个新文件夹,然后命名为要复制的文件夹名字,之后再把要复制文件夹里面的内容拷贝到新文件夹
管道可以用来在两个进程之间传递数据,如: ps -ef | grep “bash”, 其中‘|’就是管道,其作用就是将 ps 命令的结果写入管道文件,然后 grep 再从管道文件中读出该数据进行过滤。
有名管道可以在任意两个进程之间通信
有名管道的创建:
◼ 命令创建: mkfifo FIFO
◼ 系统调用创建
管道通信必须在两个进程之间进行,如果在一端,则会发生阻塞
有名管道可以在任意两个进程之间通信,而无名管道只能在父子进程之间通信
main.c
./main
信号量是一个特殊的变量,一般取正数值。它的值代表允许访问的资源数目,获取资源时,需要对信号量的值进行原子减一,该操作被称为 P 操作。当信号量值为 0 时,代表没有资源可用,P 操作会阻塞。释放资源时,需要对信号量的值进行原子加一,该操作被称为 V操作。信号量主要用来同步进程。信号量的值如果只取 0,1,将其称为二值信号量。如果信号量的值大于 1,则称之为计数信号量。
semget() | 创建信号量,或获取一个已存在的信号量 |
---|---|
semop() | 实现p,v操作 |
semctl() | 初始化,销毁 |
ipcs | 查看系统中的消息队列 |
---|---|
ipcrm | 删除 |
ipcs 可以查看消息队列、共享内存、信号量的使用情况,使用 ipcrm 可以进行删除操作
共享内存为多个进程之间共享和传递数据提供了一种有效的方式。共享内存是先在物理内存上申请一块空间,多个进程可以将其映射到自己的虚拟地址空间中。所有进程都可以访问共享内存中的地址,就好像它们是由 malloc 分配的一样。如果某个进程向共享内存写入了数据,所做的改动将立刻被可以访问同一段共享内存的任何其他进程看到。由于它并未提供同步机制,所以我们通常需要用其他的机制来同步对共享内存的访问。
物理内存共用,把物理内存映射到a的地址空间之中,然后再映射到B的地址中去。
1. #include <sys/ipc.h>
2. #include <sys/shm.h>
3. #include <sys/types.h>
/*
6. shmget()用于创建或者获取共享内存
7. shmget()成功返回共享内存的 ID, 失败返回-1
8. key: 不同的进程使用相同的 key 值可以获取到同一个共享内存
9. size: 创建共享内存时,指定要申请的共享内存空间大小
10. shmflg: IPC_CREAT IPC_EXCL
11. */
12. int shmget(key_t key, size_t size, int shmflg);
13.
13. /*
14. shmat()将申请的共享内存的物理内存映射到当前进程的虚拟地址空间上
15. shmat()成功返回返回共享内存的首地址,失败返回 NULL
16. shmaddr:一般给 NULL,由系统自动选择映射的虚拟地址空间
17. shmflg: 一般给 0, 可以给 SHM_RDONLY 为只读模式,其他的为读写
18. */
19. void* shmat(int shmid, const void *shmaddr, int shmflg);
20. . /*
23. shmdt()断开当前进程的 shmaddr 指向的共享内存映射
24. shmdt()成功返回 0, 失败返回-1
25. */
26. int shmdt(const void *shmaddr);
27.
28. /*
29. shmctl()控制共享内存
30. shmctl()成功返回 0,失败返回-1
31. cmd: IPC_RMID
32. */
33. int shmctl(int shmid, int cmd, struct shmid_ds *buf);
sem.h
1 #include"sem.h"
2 static int semid=-1;
3 void sem_init()
4 {
5 semid=semget((key_t)1234,NUM,IPC_CREAT|IPC_EXCL|0600);//全新创建信号量
6 if(semid==-1)//已存在信号量,所以创建失败
7 {
8 semid=semget((key_t)1234,NUM,0600);//成功获取信号量
9 if(semid==-1)//还是失败,代表创建信号量失败
10 {
11 printf("semget err\n");
12 }
13 }
14 else//全新创建成功,进行初始化
15 {
16 union semun a;
17 int arr[NUM]={1,0,0};
18 for(int i=0;i<NUM;i++)
19 {
20 a.val=arr[i];//信号量的初始值
21 if ( semctl(semid,i,SETVAL,a) == -1 )//信号量设置初始值失败
22 {
23 printf("semctl init err\n");
24 }
25 }
26 }
27 }
28
29 void sem_p(int index)
30 {
31 if(index<0||index>=NUM)
32 {
33 return;
34 }
35 struct sembuf buf;//定义结构体变量
36 buf.sem_num = index;//信号量下标(比信号量个数少一个,下标从0开始)
37 buf.sem_op = -1;//给信号量值-1
38 buf.sem_flg = SEM_UNDO;//标志位,当信号量没有释放时,系统会对信号量进行销毁释放
39
40 if(semop(semid,&buf,1)==-1)//对信号量操作失败
41 {
42 printf("semop p err\n");
43 }
44
45 }
46
47 void sem_v(int index)
48 {
49 if(index<0||index>=NUM)
50 {
51 return;
52 }
53 struct sembuf buf;
54 buf.sem_num = index;
55 buf.sem_op = 1;//v操作
56 buf.sem_flg = SEM_UNDO;
57 if(semop(semid,&buf,1)==-1)//对信号量操作失败
58 {
59 printf("semop v err\n");
60 }
61 }
62
sem.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/sem.h>
6
7 #define SEM1 1
8 #define SEM2 0
9 #define SEM3 0
10 #define NUM 3
11
12 union semun
13 {
14 int val;
15 };
16
17 void sem_init();//初始化
18 void sem_p(int index);//p操作
19 void sem_v(int index);//v操作
20 void sem_destroy();//销毁信号量
~
main.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/ipc.h>
6 #include<sys/shm.h>
7 #include<sys/types.h>
8 #include"sem.h"
9 int main()
10 {
11 int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
12 if(shmid==-1)
13 {
14 printf("shmget err\n");
15 exit(1);
16 }
17
18 char*s=(char*)shmat(shmid,NULL,0);
19 if(s==(char*)-1)
20 {
21 printf("shmat err\n");
22 exit(1);
23 }
24
25 sem_init();
26 while(1)
27 {
28 printf("input \n");
29 char buff[128]={0};
30 fgets(buff,128,stdin);
31 sem_p(SEM1);
32 strcpy(s,buff);
33 sem_v(SEM2);
34 if(strncmp(buff,"end",3)==0)
35 {
36 break;
37 }
38 }
39 shmdt(s);//断开映射
40 //shmctl(shmid,ipcrmid,NULL);移除信号量
41 }
test.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/ipc.h>
6 #include<sys/shm.h>
7 #include<sys/types.h>
8 #include"sem.h"
9 int main()
10 {
11 int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
12 if(shmid==-1)
13 {
14 printf("shmget err\n");
15 exit(1);
16 }
17
18 char*s=(char*)shmat(shmid,NULL,0);
19 if(s==(char*)-1)
20 {
21 printf("shmat err\n");
22 exit(1);
23 }
24
25 sem_init();
26 while(1)
27 {
28 sem_p(SEM2);
29 if(strncmp(s,"end",3)==0)
30 {
31 break;
32 }
33 printf("read:%s\n",s);
34 sem_v(SEM1);
35 }
36 shmdt(s);//断开映射
sem_destroy();
37 }
~
消息类型
ipcs -q 仅显示消息队列
在消息队列中添加消息