文件的相关操作
文件的周边函数、内存mmap、目录的函数
进程的创建(fork/vfork)
umask 是 设置权限的屏蔽字,对 创建文件有效。
chmod 是 对已经存在的文件 ,修改 权限。
truncate/ftruncate 可以 指定文件的长度(可大可小)
内存 映射 文件 mmap
rename - 重命名
mkdir - 创建新目录
rmdir - 删除目录, 只能删除空目录
chdir - 切换工作目录/当前目录(相当于cd)
fchdir
getcwd - 取当前目录(相当于pwd)
{
chdir(filename); // 切换目录
char* path = getcwd(NULL, 0); // 利用返回值获取文件当前目录
printf("path: %s\n", path);
char buf[100] = {};
getcwd(buf, sizeof(buf)); // 利用数组获取文件当前目录
printf("path: %s\n", buf);
}
示例代码
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all filesystem types */
char d_name[256]; /* filename */
};
// --------------------------------------------------
// 使用
DIR* dir = opendir("."); // 打开目录
if(dir == NULL) perror("open"),exit(-1);
struct dirent* ent;
while(ent = readdir(dir)){ // 读取某个文件或目录
printf("%d,%s,%d,%d\n",ent->d_type,
ent->d_name,ent->d_off,telldir(dir));
}
seekdir(dir,881236067); // 指定到某一offset的下一位置
rewinddir(dir); //回到开始
操作系统都是支持多进程的,每个进程都有 自己的进程ID。进程号 可以延迟重用(进程结束后,进程ID过段时间后可以继续使用)。
ps -aux(Linux)—Unix变相支持ps -aux,不直接支持
但 Unix 也 可以用特殊的方式 支持ps -aux。
whereis ps
/usr/ucb/ps -aux 可以的
kill -9 进程ID(必杀)
字母 | 含义 |
---|---|
D | 不可中断睡眠 |
S | 休眠状态 |
O | 可运行状态 |
R | 运行状态 |
T | 挂起状态 |
Z | 僵尸进程(本应关闭,但资源没有释放的进程,不是由父进程中止的) |
< | 高优先级 |
N | 低优先级 |
L | 在内存中有内存页被锁住 |
s | 其下面有子进程 |
l | 是多线程 |
+ | 前台进程组 |
如果一个进程A 启动了进程B,则A进程叫B进程的父进程,B进程叫A进程的子进程
$ ps
PID TTY TIME CMD
56370 pts/4 00:00:01 bash
125930 pts/4 00:00:00 ps
// 我们查找 bash 56370
ps -ef
liujing 56370 56363 0 Aug19 pts/4 00:00:01 bash
liujing 56363 1576 0 Aug19 ? 00:01:37 /usr/lib/gnome-terminal/gnome-terminal-server
liujing 1576 1382 0 Aug17 ? 00:00:00 /sbin/upstart --user
root 1382 982 0 Aug17 ? 00:00:00 lightdm --session-child 12 19
root 982 1 0 Aug17 ? 00:00:02 /usr/sbin/lightdm
root 1 0 0 Aug17 ? 00:00:11 /sbin/init auto noprompt
系统用pid管理进程,每个进程都有当时唯一的进程ID
程序中起作用的是 有效用户,因此,getuid和geteuid返回的都是 有效用户。
Linux/Unix 切换用户 su , 但导致的问题是这个机器本身是谁的账号登录的,所以这个第一个机器启动时登录的账号就是真实用户
切换到其它用户, 如 root , 也可以是其它普通用户, 它们就是有效用户
示例代码
printf("pid=%d, ppid=%d, uid=%d, euid=%d\n",
getpid(), getppid(), getuid(), geteuid());
// pid=126640, ppid=126639, uid=1000, euid=1000
fork()/vfork() 都可以创建子进程。
fork是通过复制父进程来创建子进程,复制 父进程的内存区域(堆、栈,全局等)。代码区不复制(代码区只读,共用不会有冲突),其它区都复制。子进程会申请新的内存空间,值和父进程对应内存空间一样。子进程不执行 fork之前的代码。但 fork之后的代码 父子进程 各 执行一遍。
fork之后,谁先执行,谁后执行,没有固定顺序,由操作系统调度算法决定
printf("begin, pid=%d\n", getpid());
pid_t pid = fork();
if (pid == -1)
perror("fork"), exit(-1);
if (pid == 0){ // 子进程中
printf("我是子进程, 我的父进程ppid=%d, 我的pid=%d\n", getppid(), getpid());
}else{ // 父进程中
printf("我是=父进程, 我的子进程pid=%d, 我的pid=%d\n", pid, getpid());
}
printf("end, getpid=%d\n", getpid());
/* 注意:有时并不能确保所有顺序都是这样
begin, pid=127438
我是=父进程, 我的子进程pid=127439, 我的pid=127438
end, getpid=127438
我是子进程, 我的父进程ppid=127438, 我的pid=127439
end, getpid=127439
*/
exit(0) 可以退出当前进程,例如在子进程中写exit(0), 退出子进程,并不会影响父进程
#include
#include
#include
#include
using namespace std;
int i1 = 100;
int b;
int main(int argc, char** argv) {
printf("begin, pid=%d\n", getpid());
int i2 = 200;
char* str = (char*)malloc(20);
strcpy(str, "abcdef");
pid_t pid = fork();
if (pid == -1)
perror("fork"), exit(-1);
int i3 = 300;
if (pid == 0){
// 子进程中
printf("我是子进程, 我的父进程ppid=%d, 我的pid=%d\n", getppid(), getpid());
i1 = 101;
i2 = 201;
i3 = 301;
b = 501;
int i4 = 401;
str[0]= 'A';
printf("i1=%d,i2=%d,i3=%d,i4=%d,b=%d,str=%s\n", i1, i2, i3, i4,b,str);
}else{
// 父进程中
sleep(2);
printf("我是=父进程, 我的子进程pid=%d, 我的pid=%d\n", pid, getpid());
//i1 = 102;
//i2 = 202;
//i3 = 302;
int i4 = 402; // 父进程中并不能直接访问子进程中的局部变量
//str[1] = 'B';
printf("i1=%d,i2=%d,i3=%d,i4=%d,b=%d,str=%s\n", i1, i2, i3, i4,b, str);
}
printf("end, getpid=%d\n", getpid());
return 0;
}
/*
begin, pid=127977
我是子进程, 我的父进程ppid=127977, 我的pid=127978
i1=101,i2=201,i3=301,i4=401,b=501,str=Abcdef
end, getpid=127978
我是=父进程, 我的子进程pid=127978, 我的pid=127977
i1=100,i2=200,i3=300,i4=402,b=0,str=abcdef
end, getpid=127977
*/
在fork时,打开文件,在父子进程中同时写文件,一个写入26个大写字母,一个写入26个小写字母
情况一:fork之前,有文件描述符,是只复制文件描述符,有没有复制文件表?
看文件偏移变量,52个,不复制文件表,测试使用fork之后,对同一个文件写入,看其大小和内容,可以确认只用了一个文件偏移量
情况二:fork之后,父子进程同时都打开同一文件,
会复制文件描述符,也会复制文件表,如果文件不加读写锁,会产生覆盖情况