码神营地-Linux学习笔记

更多关于Linux学习视频教程请进码神营地官网:www.icodegod.com

目录类型及其意思:
/boot 根目录,系统内核文件
/etc 系统配置文件
/home 用户文件
/bin 系统常用命令
/lib 系统库文件
/var 服务相关信息
/usr 用户空间
/dev 系统存放的设备文件
/proc 系统的镜像,是虚拟的
/root 根目录的家目录

文件类型:
1,普通文件、文档文件
2,目录文件 d
3,管道文件 p
4,设备文件 b,c
6,套接字 s

终端上:
~就代表的是家目录/home
普通文件不可以从终端直接进入,文件夹和目录才可以进入
Linux 文件属性
使用命令 ls -l或者ll来查看当前目录下的文件的详细信息

  • rwx rwx rwx 1 root root Otc Test
    属主 同组 其他 连接数 档案拥有着 所属群组 时间

【r】 代表可读
【w】 代表可写
【x】 代表可执行

chmod [who][opterator][mode][文件或目录名]

或者chomd 767数字 (r 4,w 2,x 1)
umask一般是用在你初始创建一个目录或者文件的时候赋予他们的权限。
  这里要说明两点:
  1、针对目录来说x权限代表可以进入该目录,所以说对于这个权限初始赋值是没什么问题的;
  2、针对文件的x的权限代表执行,这个风险太高,所以一般权限初始赋值必须去掉x的;
  [root@www ~]# umask
  0022
  这四个字母代表什么?
  首先说明一点,上面四个数字代表是赋值初始化准备丢弃的权限。(相对应文件来说,x权限就算没说明出来丢弃一样必须默认丢弃)
  第一个0代表suid 丢弃的权限;
  第二个0代表本文件/目录拥有者什么权限都没丢弃(如果是文件,x权限除外,为什么看看上面解释);
  第三个2代表本文件/目录的用户组丢弃了w权限(如果是文件那么它的x权限也丢弃);
  第三个2代表本文件/目录的其他用户能使用的权限只有有r和x(文件除外)。
  综合上面所说如果你新创建一个文件那么它的权限是:-wr-w–w-- 即是:644
  如果你新创建一个目录的话那么它的权限是:dwrxw-xw-x 即是:755
  如果你要修改unask熟悉直接:
  [root@www ~]# umask 002

ls -l 表示显示全部信息
ls -al 表示显示隐藏文件
touch 创建普通文件
mkdir 创建目录
rmdir 删除目录
cp 拷贝 cp -r [文件名]表示拷贝一个目录
cp [文件名] 表示的是拷贝一文件
mkdir 只能删除空的文件夹
rm 删除不是空的文件夹和文件
rm -r
rm * 删除当前文件夹下的所有东西

mv 粘贴和剪切可以更换文件名字
(相当于剪切下来粘贴到另一个文件夹)

绝对路径:从根目录开始 /home/stu/file1
相对路径:从当前目录开始 file1

cat filename 显示文件信息
more 分屏幕显示 q退出,加空格显示下一屏
less [文件名] 可以通过方向键来查看,q退出
head [-2][文件名](默认是10行)
tail [-2][文件名](默认是10行)

vi [文件名] 进入文件
退出 :q!
vi test.c (没有创建的文件夹)
vi的三种模式:
1,命令模式(插入模式esc进入命令)
2,插入模式(命令模式i o a进入插入)
3,末行模式(命令模式:/ ?进入末行)
( :w :q :wq :q! )
拷贝: n+yy
粘贴 : p
删除/剪切 : n+dd
撤销 : u
一部分不要了: C
:set num 设置行号
:set nonu 取消行号
:n 代表第几行
/(?)
GG 到最后一行
不要同时打开多个vi,如果异常退出,就要先删除.main.c 隐藏的文件
x : 删掉一个字母
r 修改字符: 修改字符
R : 替换一个字符串,也就是去全部替换

光标移动、定位:

1、H (左) J (下) K(上) L(右)

2、光标移到行尾 shift + 4 即 $

3、光标移到行头 shift +6 即^

4、光标到文件行末 shift +g

5、光标到文件的某行 n+shift +g

6、光标到当前屏幕底 shift +L

7、到当前屏幕中间 shift + m

8、到当前屏幕头 shift +h

9.向下翻页 ctrl +f
10、向上翻页 ctrl+b

cal :查看日期
data :查看时间
su :切换用户

===================================================

进程 用户(多用户系统)
id 查看当前用户的id信息
ps 查看当前进程
ps -f 显示更多的进程信息
bash :shell 命令解析器的其中一个实体(shell有很多实体)
用exit退出shell命令

cd ~ 返回加目录
cd / 根目录

进程有关操作

进程(多个进程之间可以区分) 用户
进程:pid(唯一可以标识程序) uid
副进程:ppid
用id 命令显示进程信息

ps 显示当前用户正在运行的进程,而不是系统的进程
ps -f 显示当前用户正在运行的进程更多的信息
ps -ef 显示系统中运行的进程

bash的进程是某个进程的副进程
bash不会终止,除非终止该程序,相当于程序中的提示输入信息
ps是通过复制bash得来

shell命令解释器
通过exit退出shell命令

ls是带有–color参数的命令

sleep 执行阻塞命令 sleep + 阻塞时间 (程序持续运行多长时间)
Ctrl + C 可以对出阻塞状态
sleep + 阻塞时间& 进程在后台运行,不影响前台操作

jobs 查看在后台运行的进程
jobs -l 显示更多后台运行进程的信息

Ctrl + z 停止
bg %任务号(通过jobs查看),将sleep进程从前台转到后台运行
fg %任务号(通过jobs查看),将sleep进程从后台转到前台运行

kill + pid,结束进程,但是在某种情况下可能不能结束(只是系统给它发信号,让他自己终结)
kill -9 pid,强制终止进程
pkill -9 sleep 全部终止所有进程
stop %n 命令
挂起一个后台运行的任务

管理员使用的系统管理命令:
adduser命令:adduser + 用户名 大小写敏感,新增用户没有口令
passwd命令:passwd + 用户名

#环境变量 :echo $str (一般的环境变量会大写)
echo : 表示输出相当于printf(可加‘’,也可加“”不影响)

#变量 str = hello 加#表示屏蔽
echo str 输出字符串
echo $变量名
echo + $环境变量 (环境变量一般大写)
echo $HOME 加目录的位置
echo $PATH

Ctrl + F1 切回图形化界面

who :显示计算机登陆的用户
who am i :显示当前的用户
users :计算机的所有使用者

find 路径 -name filename.c(按名称搜索)
man 命令(库函数,etc) :帮助手册
(1是命令,2是系统调用,3是库函数)
eg: man 2 kill

grep “字符串” 文件名: 在文件中查找所有含有该字符串的串
grep -i “” :忽略大小写查找
grep -c “” : 不显示结果,显示查找了多少个
ls | grep “file” :从管道中查看是否有该文件(用的比较多)

wc -l filename :按行统计
wc -c filename :
wc -w filename :按单词统计(以空格为间隔)

===================================================
回顾vim用法
n+yy 复制

n+dd 剪切n行
p粘贴

:set nu 设置行号 set nonu 去掉行号
:n 定位到第n行

所有的删除都是剪切式删除

当一个terminal 已经用vi打开一个文件以后,不能再另一个terminal中打开那个文件
或者非正常关闭一个文件,则会产生一个.swp文件,则ls -a 找到那个swp文件
然后删除rm该文件即可编辑了

ps:查看进程

关机命令 shutdown 在root下执行
shutdown -r now 立刻重启
shutdown -c 取消关机的命令,会将该信息发送到所有用户
shut -h + time 多少时间之后关机(关机后不重启)

halt 普通用户都可以立刻关机
还有reboot 重启
init 0 关机 init 6重启

系统运行级别 0~6
系统运行级别设置

0 停止运行,所有进程终止,关机  
1 单用户模式,用于维护系统,只有少数进程运行  
2 不带网络的多用户  
3 完整的多用户模式,优先进入文本字符界面  
4 保留,用户可以自给定义  
5 图形界面的多用户  
6 重起系统

runlevel 查看当前运行级别
root用户下 init n 然后回车
如init 1 切换到单用户模式,单用户就是管理员

5是默认的有图形界面的模式

运行级别的配置文件
/etc/inittab
ctrl + Fn 切换到某个用户模式

开机时按esc可以切换进度条和具体信息的窗口

===================================================
用户的创建
etc/passwd

1 root: x: 0: 0: root: /root: /bin/bash
编号 用户名 密码占位符 用户ID 组ID 用户全名 家目录: bash是用于交互的shell程序

/sbin/nologin 以下的用户是不能登录的,这些用户其实就是系统的一些软件,这些用户其实就是为了和这些应用软件进行交互

只有用户ID在500或者以上的才可能登录

/etc/group 是用户组配置文件
/etc/shadow 是相应用户的用户密码的密文 !!表示没有启用
增加用户:
useradd usrname
passwd usrname
然后输入新的密码
删除用户的时候是默认不删除家目录的
userdel usrname 如果加个 -r 表示删除家目录和邮箱mail box
passwd配置文件中就将usrname的密码删除了

如果再增加一个同名的用户,则会给出警告,家目录和mail box都存在了

看邮件:mail
如果一个用户正在登陆,则不能删除该用户
man 命令name 查看命令name的帮助文件

单用户模式即维护 破解管理员密码

tar c(create)f()v my.tar filelist

tar c(create)f()v my.tar file1 file2tar

打包:
tar
c:创建文件
f:指定目标位文件不是设备
t:列出内容但不真正释放
v:显示tar命令执行的详细过程
x:从档案文件中释放文件
z:在GUN版本的tar中解压gzip的文件

tar x(释放)f(指定目标文件不是设备)v(显示响应信息) my.tar     释放以后压缩包还在
tar t(列出文件但不是放文件)f my.tar 查看压缩包里面的东东但是不解压

示例:
tar cvf mylib.tar bill.c fred.c lib.h makefile

压缩:
gzip mylib.tar
解压:gzip –d mylib.tar.gz 解包: tar xvf mylib.tar

GNU版: 压缩: tar zcvf mylib.tgz filelist 解压:tar zxvf mylib.tgz
gzip mylib.tar 生成 mylib.tar.gz

解压:gzip –d mylib.tar.gz
解包: tar xvf mylib.tar

yum仓库安装软件

将光驱cdrom挂载到mnt目录中

mount /dev/cdrom /mnt

regular:常规的文件

======================================================

如何安装gcc
借助yum,yum是安装和卸载软件的工具
(1)yum仓库,很多种类的软件的安装包。安装包在ISO的镜像文件中。
(2)配置文件
(3)通过命令安装gcc,yum install gcc.XXX

在root下的安装步骤:
cd /mnt
cd /dev/cdr + table
cd /dev/cdrom2 /mnt 出现mount: block device /dev/sr0 is write-protected, mounting read-only
cd …
cd /mnt
ls
cd /etc/yum.repos.d/
pwd
ls

				vi text.repo
				[serid]
				name=test
				baseurl=file:///mnt
				gpgcheck=0

				yum repolist
				ls
				yum search gcc
				yum install gcc.i686 -y

======================================================

/var/www/html存放的是发布的网站
ps -ef | grep httpd

httpd 在linux6.5中是个apache http server
安装完以后,进入到/var/www/html中,编辑一个简单的网页index.html,并让其显示

如果不是index.html则要在域名之后加上首页面名字

配置ip

/etc/sysconfig/network-scripts
修改ifcfg-eth0
DEVICE=“eth0”
BOOTPROTO=“dhcp”
NM_CONTROLLED=“yes”
ONBOOT=yes
TYPE=“Ethernet”
UUID=“f59b2ca4-79c1-4300-a606-4c5e396162fb”
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
NAME=“System eth0”
HWADDR=00:0C:29:DE:56:2A
PEERDNS=yes
PEERROUTES=yes

service network start

ftp服务:
yum search vsftpd 查询安装包版本 最后的d表示守护进程
找到vsftpd.i686 进行安装
服务在var/ftp/pub目录下

lftp +ip

homework:ftp服务器、apache服务器+访问网页、虚拟机和主机通过ip地址访问
[root@localhost network-scripts]# vi ifcfg-eth0
[root@localhost network-scripts]# iptables -F
[root@localhost network-scripts]# setenforce 0
[root@localhost network-scripts]# service network start
Bringing up loopback interface: [ OK ]
Bringing up interface eth0: Error: No suitable device found: no device found for connection ‘System eth0’.

RTNETLINK answers: File exists

127.0.0.1 :表示当前用户的IP

127.0.0.1/index.html :表示具体的网页显示

IP: 唯一标识主机的

iptables -F 或者 setenforce 0 :关闭防火墙

Gcc下C文件的编译和运行:
1.main.c 高级 第一种做法: gcc -c main.c

汇编                        gcc -c add.o

机器语言                   gcc -o main main.o add.o
                                   
 ./main :全路径执行程序

第二种做法:
合并做法: gcc -o main main.c
./main

incldue<unistd.h> Linux中常用的头文件

gdb :调试用的注意:如果需要调试应该命令后面加上 –g
gcc –o my my.c -g

使用makefile帮助执行文件:

 vi makefile(创建一个makefile文件)
 或者:make -f main  ---->指定makefile的文件名
 (如makefile的名字是bbb,则上述make -f bbb  即bbb为makefile 来执行make 动作)

 all :main (名字)
 
 main : main.o add.o max.o  ( 依赖关系)
         gcc -o main main.o add.o max.o ( 规则,必须以tab键开头)
 main .o : main.c                                    
         gcc -c main.c
 add.o : add.c (add.h可以加上也可以不加)
         gcc -c add.c
 max.o : max.c(max.h)
         gcc -c max.c 
 clean :
         rm -rf *.o main(清理)

  
运行makefile时,从上往下开始执行 依次执行,
倒数第二步是找到max.o 依赖的是max.c 执行gcc -c max.c
最后执行gcc -o main main.o add.o max.o
当不需要的程序用#注释掉

make 用法:
make -n:表示不编译,只模拟一次
如果注释掉命令,则会自动推到,用cc来编译生成main可执行程序
make -f main  ---->指定makefile的文件名

=============================================================

库文件:
库的类型:前缀为lib,后缀为[.a]代表静态库
后缀[.so]代表动态库

静态库的使用:
静态库静态库,也称作归档文件,按惯例都以.a 结束。

1)先将.c文件都编译成.o文件
2)使用命令:
ar crv libfoo.a bill.o fred.o
(将bill.o 和fred.o一起打包生成libfoo.a)
r是添加进库 c是create v是显示信息view

   静态库的使用:
   gcc –o main  main.o  -L.  -lfoo
   -L.表示当前路径

切换到root用户下:
cp libfoo.a /usr/lib
则编译main.c的时候就不用再显式指定连接libfoo.a 了,系统自动添加该libfoo文件

只需用以下命令就可以了:(也需要指定用到哪个lib文件)
gcc –o main main.o -lfoo.a
-lfoo.a:-l表示要用连接库,foo.a表示库文件名
步骤:
1:做库
2:通过main来用库

动态库:运行时才将库加载到内存中运行
共享库:程序本身不包含函数代码,而是引用运行时可访问的共享代码。
编译命令:
gcc –shared –fPIC test_a.c test_b.c –o libtest.so
–fPIC是编译共享库所需的参数
ldd main 查看可执行程序main所依赖的关系
libmfoo.so => not found
libc.so.6 => /lib/libc.so.6 (0x00403000)
/lib/ld-linux.so.2 (0x003dd000)

如果有两个名字相同,但是一个是静态库,另一个是动态库时,系统优先使用的是动态库,
也可以指定使用静态库

如何调试程序:
gcc 。。。。。。-g 显示生成debug版本,只能是debug版本才能进行调试,因为只有debug 版本才有调试信息
gdb调试器
gdb main 运行main
l显示代码(list n:查看多少行代码)
b n:在第n行加breakpoint
delete n:删除第n行的断点
info break 查看断点位置及编号
r 运行
p 查看变量内容
c 继续运行
bt 查看函数调用栈,即查看当前运行到那个位置了
q 退出

=============================================================

exit(0) :在#include<stdlib.h>中

静态库:动态库:共享库:注意三者区别

fork: 复制进程

   进程:一个程序正在执行的过程
   PCB:进程控制块(P:Processing,C:Ctrl,B:Block)
   进程状态:运行(时间片用尽时就转为就绪状态),就绪,阻塞(等待)

创建新程序:
1.用fork复制一个进程(子进程接着父进程的后面进行)
(fork返回两次:子进程一次,父进程一次,实质是两个不同的进程)
2.在把复制的进程替换掉当前程序

PID = 1的表示复制进程中第一个被复制出来的子进程,它没有父进程
其他的每个都有父进程即:以后的进程都是fork+exec产生的进程
(ID号是从小到大的增长,fork时候,子进程ID是逐渐增大的)

即:fork+ exec

操作系统:(OS)
1.进程管理
2.内存管理
3.文件管理

内存:装载程序到内存,内存不一定连续
有一个物理页和逻辑页(虚拟页),它们之间有一个映射(页映射)

关于fork()的相关问题:

1.不能写for(int i= 0;)操作,只是在VS下支持
且在打印时候用sleep(1):使得两个进程之间有一个区分,有一个缓冲

2.当两个程序并发运行时候,程序在终端的打印可能是交替打印的,
但是他们是同时进行的 (fork的俩进程是同时进行的,但是终端只有一个)

3.整个fork()实在操作系统中完成的,运行是从fork()返回的地方开始的

4.两个进程的逻辑地址相同,但是他们的物理内存是不相同的,
两个进程必然会分配不同的内存,不可能共用一块内存

5.fork执行完后,父进程中的状态会拷贝到子进程中

6.pid():获得子进程的id; ppid():获得父进程的id

7.写时拷贝:当一个进程的某一个地方需要改写时,
此时会按页分配相应的内存拷贝一个进程给它进行改写

=============================================================
僵死进程:(defunct)产生条件有两个:
1.子进程先于父进程结束。
2.父进程没有调用wait()来查看子进程信息。父进程没有获得子进程的pcb信息,子进程一结束就变成僵死进程。
pid:子进程id。
ppid:父进程id。
Ppid=1:是fork进程的第一个进程,为init.

僵死进程为什么第二次ps时候没有了?:因为它的父进程不存在了,父进程的父进程保证不让父进程变成僵死进程,直接挂到init()。

父进程的父进程是:bash(也就是shell),所有的在shell下的进程的父进程都是bash.

解决僵死进程办法:
父进程调用wait()来获取子进程的pid信息。
./fork & :把进程转到后台。

可以利用 int val = 0;
pid_t = wait(&val);
If(WIFEXITEO(val))
    {
Printf(“id = %d,val = %d\n”,id,WEXITSTATUS(val));
    }
关于主函数的参数:

  1. Int main(int argc,char *argv[])(其中argv表示参数个数,argv[]表示的是参数包含的信息)
    第一个参数表示的是当前程序的名称。
    2.int main(int argc,char *argv[],char *envp[])(其中增加的envp[]表示环境变量信息)

单独获取环境变量的信息:getenv(环境变量名),函数的原型为:char* getenv(char *name)。
(如果不改变代码的情况下,可以使用编号来查看)

程序中用的malloc申请空间时,在使用fork()函数来复制进程时,当程序运行结束后,即使没有使用free()还是不会有内存泄露。

Malloc能分配的最大空间取决于剩余的内存大小
系统调用:

思考题:1.Fork() || fork() 会产生几个进程?

答:
打印结果为3次。执行第一个fork()时候,当父进程执行完了之后,父进程返回值为0,子进程返回值为不为0,所以此时父进程不执行了,利用子进程在执行第二个子进程,然后又创建一个fork()子进程。
相当于是父进程复制了两次,创建了两个子进程,再加上父进程总共是3个。

    2.
       i= 0;
       For(;i<2;i++)
       {
            Fork();
            Printf(“A\n”);
       }        (会打印几次?)

答:
打印结果为6个A。如果拿掉\n则打印结果为8个A。

    3.int main()
      {
            Printf(“A”);
            Write(1,”B”,1);
            Fork();
            Exit(0);
      }

答:
打印结果为BA A。第二个A是fork()时候被复制过来的,因为子进程的复制状态会跟父进程一样,把缓冲区也拷贝过来了,所以在调用exit时候冲刷缓冲区时,也会冲刷子进程的缓冲区。

=============================================================
文件描述符:

Vi main.c

	#include<stdio.h>
	#include<unistd.h>
	#include<string.h>
	#include<assert.h>
	#include<fcntl.h>     //文件操作的头文件
         
int main()
{
int fd = open(“./my.txt”,0_WRONLY|0_CREAT,0600);//(open函数含有三个参数,返回值为整型int)
assert(fd != -1);
printf(“fd=%d\n”,fd);
int n =write(fd,”hello world”,5);
printf(“n=%d\n”,n);
close(fd);
exit(0);
}

Vi file

运行结果为:
fd=3
n=10
3:库函数;
2:系统调用
1:命令

总是挑最小的未被占用的数字。

vi file
abcdefg

Vi main

Int main()
{
Int fd = o
pen(“file”,o_WRONLY);
Assert(fd != -1);
Char buff[128] = {0};
Pid_t pid = fork();
Assert(pid !=-1);
If(pid == 0)
{
    Read(fd,buff,1);
    Printf(“child buff=%s\n”,buff);
    Sleep(1);

    Read(fd,buff,1);
    Printf(“child buff=%s\n”,buff);
}
Else
{
    Read(fd,buff,1);
    Printf(“parent buff=%s\n”,buff);
    Sleep(1);

    Read(fd,buff,1);
    Printf(“child buff=%s\n”,buff);
}
Close(fd);
Exit(0);
}

运行结果:
Child buff = a
Parent buff = a
Child buff = b
Parent buff = c
[sufeng@dddsd]$child buff =d

思考题:分析下面代码的打印结果为什么不同?

1.Int mian()
{
Printf(“hello world\n”);
Sleep(3);
Exit(0);
}

2.Int main()
{
Printf(“hello world”);
Sleep(3);
Exit(0);
}


3.Int main()
{
Printf(“hello world\n”);
Sleep(3);
_exit(0);
}

答:
前面两个1和2区别:
/n具有刷新缓冲区(为了减少与用户态到内核态的频繁交换)的作用,printf相当于是一个标准输出的系统调用(1),实际上是底层调用一个write(1,“hello”,5)函数,printf是收集多个数据,而只切换一次。fflush(stdout)(强制刷新输出) 函数。

后面1和3的区别:
exit()函数本来是具有冲刷缓冲区的功能,_exit()现在则是变得使得exit()函数跳过了冲刷缓冲区功能,所以屏幕上没有输出。

=============================================================

系统调用:

execl()有三个参数,最后一个为一个空指针,如果execl执行了,那么它后面的程序将不会被执行。

例:

Int main()
{
    Printf(“main running(pid = %d)\n”,getpid());
    Execl(“/bin/ps”,”ps”,”-f”,(char*)0);
    Printf(“main over\n”);
    Exit(0);
}



Int main()
{
    Printf(“main running(pid = %d)\n”,getpid());
    Execl(“./my”,”my”,”hello”,(char*)0);
    Printf(“main over\n”);
    Exit(0);
}



Int main(int argc,char *argv[],char *envp[])
{
Int i;
For(i =0;i<argc;i++)
{
 	Printf(“argv[%d] = %s\n”,argv[i]);
}
For(i = 0;envp[i]!=NULL;i++)
{
Printf(“envp[%d]=%s\n”,i,envp[i]);
}
Exit(0);
}

=========================================================

Eg1:

	#include<stdio.h>
	#include<stdlib.h>
	#include<assert.h>
	#include<string.h>
    #include<unistd.h>

Int main(int argc,char *argv[],char *envp[])
{
    Printf(“main:pid=%d\n”,getpid());
    Char*myenvp[]    ={“MYSTR=hello”,”MYPATH=/home/stu”,0};
    Char * myargv[]={“test”,”-f”,0};
    Execl(“/bin/ps”.”ps”,”-f”,(char*)0);
    Execlp(“ps”,”ps”,”-f”,”(char*)0”)
    Execle(“/bin/ps”,”ps”,”-f”,(char*)0,envp);
           Execle(“./test”,”test”,”aa”,”bb”,(char*)0,myenvp);
    Execv(“/bin/ps”,”myargv”);
    Execv(“./test”,myargv);
    Execvp(“test1”,myargv);
    Execve(“/bin/ps”,”myargv.myenvp”);
    Execve(“./test1”,myargv,myenvp);
        Perror(“exec errot”);
Exit(0);
}

Eg2:

A
	#include<stdio.h>
	#include<stdlib.h>
	#include<assert.h>
	#include<string.h>
	#include<fcntl.h>
	#include<unistd.h>

Int main(int argc,char*argv[],char*envp[])
{
    Int fd = open(“./file”,O_RDONLY);
    Asseert(fd !=-1);
    Pid_t pid= fork();
    Assert(pid !=-1);
    If(pid ==0)
    {
        Char buff[8]={0};
        Sprintf(buff,“%d”,fd);
        Execl(“./my”,”my”,buff,(char*)0);
 	  	 Perror(“execl error”);
        Exeit(0);
    }
}

B
另一个文件file中有

Helloworld

还有另外一个文件my.c
C

	#include<stdio.h>
	#include<stdlib.h>
	#include<assert.h>
	#include<string.h>
	#include<fcntl.h>
	#include<unistd.h>




Int main(int argc,char*argv[],char*envp[])
{
Int i;
For(i =0;i<argc;i++)
{
 	Printf(“argv[%d] = %s\n”,argv[i]);
}
    Int fd= 0;
    Sscanf(argv[1],”%d”,&fd);
    Char buff[128]={0};
    Read(fd,buff,127);
    Printf(“buff=%s\n”,buff);
    Close(fd);
    Exit(0);
}

Execle();//p表示path,可以不提供路径
Execlp();//e表示环境变量,表示要传入环境变量,其实是可以从main函数的参数列表中获取环境变量。
Execv();
Execvp();
Execve(“./test1”,myargv(参数数组),myenvp(环境变量数组));//
Perror(“exec error”);

信号:
信号响应方式:默认模式 (0) SIG_DFL
忽略模式 (1) SIG_IGN
自定义模式(其他值) fun

信号在头文件#include<signal.h>中。
信号响应方式相当于是一个软件中断,

会用到两个系统调用:
1. Signal 系统调用
2. Kill系统调用

	#include<stdio.h>
	#include<stdlib.h>
	#include<assert.h>
	#include<string.h>
	#include<fcntl.h>
	#include<unistd.h>
	#include<signal.h>

Void fun(int sig)
{
      Printf(“sig=%d\n”,sig);
      Signal(sig,SIG_DFL);//恢复默认的处理方式
}

Int main()
{
    Signal(SIGINT,fun);
    While(1)
        {
             Printf(“main run\n”);
             Sleep(1);
        }
}

=========================================================

	#include<stdio.h>



Int main(int argc,char *argv[])
{
    If(argc <2)
    {
        Return 0;   
    }
    Pid_t pid;
    Int sig;
    Sscafnf(argv[1],”%d”,pid);
    Sscanf(argv[2],”%d”,&sig);
    If(kill(pid,sig) == -1)
    {
        Perror(“kill error”);
        Return 1;
        }
       Printf(“kill success\n”);
}

信号的发送过程及其接受过程:

解决僵死进程的三种方法:
1.用一个wait()阻塞
2. 连续使用两次fork();(使他子进程结束后,由内核发送信号给父进程让他变为init(),使得子进程不会产生僵死进程)
3. 调用默认的signal(SIGCHLD,SIG_IGN);

=======================================================================

ls -i
iNode结点相同,则是指同一个文件

ln main main1 做硬链接,即main 和main1只是两个名字,指的都是同一个文件,相当于对一个文件有两个入口,因为他们的iNode节点号是相同的。
剪切的命令,现在目标地址做一个欲剪切的文件的硬链接,在将本地的文件删除,(其实只是删除了iNode节点数)即实现了文件的剪切。

符号链接:相当于快捷方式

su命令: 如何先把自己变为管理员,才执行用户的切换 unit4.5
bin之下,su带有权限s 表示不管是谁将这个程序运行起来,他的身份都是属主的身份,所以su命令运行起来以后用户本身就是管理员,此时才可以切换用户。

Shell的雏形:

While(1)
{
   Fget(buffer);
   解析命令 : ls   pwd    ./main   vi  gcc
   Pid = fork();
   If(pid ==0)
        {
             Exec(命令)//
             Printf(“error”);
             Exit(0);
        }
}

Wait();

 进程之间的通信:

1.到文件是在内存中创建的,不是在磁盘中。
2.Read可以操作任意一种文件描述符,读取管道时候,如果管道中没有 数据,那么read会产生阻塞。
3.如果管道的写端被彻底关闭了,那么read就返回一个0,(正常情况下就会有阻塞,且正常返回非0),执行close就是彻底关闭了。

进程间通信:
管道:有名,无名
信号量 共享内存 消息队列
套接字 socket

过程如下:

有名管道(命名管道):

1.管道只有一个,在内核中,在进行fork时,管道不进行复制。
2.对于有名管道fifo,一个管道,必须要两个进程才能正常打开,一个打开读端,一个打开写端。
3.为什么两个进程中打印的fd值是相同的都为3?
答: 因为0,1,2都已经被占用,所以最小的数字是3,与他们是否为统一管道没有关系。

4.创建有名管道文件方式:
#mknod sampleFIFO p (mknod是个库函数)
#mkfifo –m 0666 sampleFIFO

5.处理写端异常的信号SIGPIPE。

6.管道缓冲区操作示意图:

read和write的几种特殊状态:

===============================================

信号量:

操作系统:信号量 是用来同步进程的
P(semopt实现) v (semop实现)
+1 v 释放资源
-1 p 获取资源 阻塞

4.8.3 信号量的实例——semtool,交互式的信号量使用工具
1. 背景知识
semtool 工具通过命令行参数来决定它的行为,这样它可以被方便的应用于 shell 脚本
中。 semtool 提供了和信号量有关的全部功能,包括创建信号量、操作、删除信号量对象以
及更改信号量权限等。使用它我们可以在命令行上控制资源的共享。
2. semtool 的命令行语法
建立信号量对象:
semtool c (number of semaphores in set)
锁定信号量:
semtool l (semaphore number to lock)
解开信号量的锁定
semtool u (semaphore number to unlock)
改变信号量的权限
semtool m (mode)
删除信号量对象
semtool d
3. semtool 的使用举例
semtool c 5
semtool l
semtool u
semtool m 660
semtool d

原子操作

临界区:访问临时资源的代码段
临界资源:只允许一个资源对资源进行操作。

IPC——CREATE:进程间通讯
1.ipcs 命令
ipcs 命令在终端显示系统内核的 IPC 对象状况。
ipcs –q 只显示消息队列
ipcs –m 只显示共享内存
ipcs –s 只显示信号量

2.ipcrm 命令
使用 ipcrm 命令强制系统删除已存在的 IPC 对象。
它的命令格式如下:
ipcrm <msg | sem | shm>
ipcrm 后面的参数指定要删除的 IPC 对象类型,分别为消息队列( msg)、信号量( sem)
和共享内存( shm)。然后需要给出要删除对象的标识符。标识符可以通过 ipcs 命令来取得。

共享内存:

Shamget((key_t)1234,256,IPC_CREAT)//表示创建一个共享内存
Shmat(shmid,NUL,0)//表示断开共享
Shmdt(ptr)//表示移除共享内存

两个进程的同步映射:用两个信号量(或者是一个信号量)实现一个进程写入,一个进程读出

umask:表示掩码,掩码为多少,那么创建的文件中 就没有什么权限。

消息队列:

2. msgtool 的命令行语法
发送消息:
msgtool s (type) “text”
取得消息:
msgtool r (type)
修改权限:
msgtool m (mode)
删除消息队列:
msgtool d

===============================================================

ipcs -q +ID :查看消息信息
ipcrm -Q+ID:删除消息

接受端的msgrcv函数中参数0表示接受不区分的消息类型。

shelll:
awk -F. ‘{print $1}’file > file1 表示打印$1中的以’.’作为分隔符的第一个域内容
awk -F: ‘{print $1”\t”$3}’passwd 表示打印第一列和第3列的内容
awk -F: BEGIN‘{print $1”\t”$3}’passwd 表示打印第一列和第3列的内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值