进程状态,用下面的代码中的一个给出:
D 不可中断 Uninterruptible sleep (usually IO)
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程
< 高优先级
N 低优先级
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组
l 多线程,克隆线程
UID:进程的用户ID
TIME:进程使用的总CPU时间
COMMAND:执行进程时的命令
USER:进程所有者
%CPU:进程自最近一次刷新以来所占用的CPU时间和总时间的百分比
%MEM:进程使用内存的百分比
VSZ:进程使用的虚拟内存大小,以K为单位
RSS:驻留空间的大小。显示当前常驻内存的程序的K字节数
START:进程的起始时间
NI 进程的优先级值,较小的数字意味着占用较少的CPU时间
PRI 进程优先级。
WCHAN 进程等待的内核事件名
##### Linux进程状态:
运行态
停止态
僵尸态
死亡态
阻塞态
可中断的阻塞态
不可中断的阻塞态
进程信息存在:/proc目录下
>
> 进程的创建
> 进程创建技术:
> 1.完美拷贝
> 几乎拷贝父进程的所有内容,除了父进程的PID,PCB信息
> 2.写时拷贝
> 开辟好进程基本管理信息后,共享父进程的数据和代码,只有
> 需要更改时,才拷贝
> 较为节省内存开销,所以用的较多
> Linux 2.6版本之后,大多使用写时拷贝
>
>
>
fork: /需要包含的头文件/ #include <unistd.h> /* *函数名:fork *函数功能:创建子进程 *函数参数:void *函数返回值:pid_t * >0: 父进程,代表子进程的pid * ==0: 子进程 * -1: fork失败 */ pid_t fork(void);
vfork clone system:<在正式工作时,不建议使用,容易产生死锁> /需要包含的头文件/ #include <stdlib.h> /* *函数名:system *函数功能:fork一个子进程,执行一条shell指令 *函数参数:const char *command:指令内容 *函数返回值:int:见manual / int system(const char * command); sleep(): /需要包含的头文件/ #include <unistd.h> / *函数名:sleep *函数功能:让进程/线程睡眠指定的秒数 *函数参数:unsigned int seconds:指定睡眠的秒数 *函数返回值:unsigned int:成功返回sleep的时间,失败返回0 */ unsigned int sleep(unsigned int seconds); fork(): 1.创建一个子进程 2.2.6以后用写时拷贝,之前用完美拷贝 3.子进程和父进程执行顺序不确定 4.有两个返回值, >0:为父进程,返回值代表子进程的pid ==0:为子进程,返回值为0 vfork(): 1.创建子进程,阻塞父进程 2.子进程先执行 3.使用的是写时拷贝 4.有两个返回值, >0:为父进程,返回值代表子进程的pid ==0:为子进程,返回值为0
clone(): 不管是fork()还是vfork(),底层实现都是clone() 该函数返回子进程的进程号,可以有选择性的拷贝 父进程的内容。
system(): fork() + execl() 创建一个进程,并执行一个shell命令 不建议执行耗时命令,容易产生死锁的情况
##### 进程的执行
exec函数族:
一般用来执行程序,而不是程序员自己灵活编写的代码
要求执行的是可执行文件。
当判断是否为子进程时,直接写相应的代码
这种方式比较灵活
system
同execl,但容易发生死锁
exec x x:
l e
v p
第五位的选项:
l:命令行参数以枚举形式输入,包含命令本身,以NULL结尾
v:命令行参数以指针数组形式传入,即把list内容写入指针数组
第六位的选项:
e:在指定的位置中执行查找可执行文件
p:在系统环境变量中执行查找可执行文件
exec函数族只能执行指定的可执行文件,是一种不够灵活的执行特定任务
的方法,掌握 execve execlp就可以了
##### 进程的销毁
exit: 调用退出处理函数 清理I/O缓冲区 _exit: 没有上述操作
获取进程表识:
#include <sys/types.h>
#include <unistd.h>
获取当前进程的pid
pid\_t getpid(void);
获取父进程的pid
pid\_t getppid(void);
标准IO缓冲区:
缓冲区的分类:
全缓冲:普通文件
行换成:stdin,stdout
无缓冲:stderr
ANSI C(C89)要求缓冲具有以下特点:
1.当且仅当标准输入和标准输出并不涉及交互设备时,它们才可以使用全缓冲。
这里并没有交代如果标准输入和标准输出涉及交互作用设备时,它们使用无缓冲还是行缓冲。
大多数系统默认使用下列类型的缓冲区:
1.标准错误是不带缓冲区的
2.如果涉及终端设备的流,则它们是行缓冲的
3.否则是全缓冲
注意:终端牵扯标准输入/输出流(stdin/stdout)
在我们使用的linux/ubuntu中:
全缓冲的大小为:4096 Byte
行缓冲的大小为:1024 Byte
如何验证全缓冲的大小:
原理:缓冲区存不下数据的时候,会刷新缓冲区(正常情况)
注意:为了避免进程退出刷新缓冲区,需要\_exit()函数来做这件事情
或者使用while(1)还阻塞进程,防止进程退出(不建议使用,比较难理解)
例子:
#include <stdio.h> #include <unistd.h>
int main()
{
FILE \*fp = NULL;
fp = fopen("a.txt","r+");
if(NULL == fp)
{
puts("open file error.");
return -1;
}
int i = 0;
//当缓冲区中的数据<=4096,在没有其他强制刷新的情况下,不会
//清空缓冲区,只有当缓冲区中的数据>4096个字符时,才会刷新
for(i = 0; i < 4096; i++)
{
fputc('a',fp);
}
\_exit(0);
}
输出结果:执行之后,a.txt没有写入数据
-rw-rw-r-- 1 farsight farsight 0 May 6 19:37 a.txt
上面的实验结果说明:缓冲区没有满,数据没有写入,也证明了大小为4096
#include <stdio.h> #include <unistd.h>
int main()
{
FILE \*fp = NULL;
fp = fopen("a.txt","r+");
if(NULL == fp)
{
puts("open file error.");
return -1;
}
int i = 0;
//当缓冲区中的数据<=4096,在没有其他强制刷新的情况下,不会
//清空缓冲区,只有当缓冲区中的数据>4096个字符时,才会刷新
for(i = 0; i < 4200; i++)
{
fputc('a',fp);
}
\_exit(0);
}
输出结果:执行之后,a.txt写入数据,并且只写了缓冲大小个数据
-rw-rw-r-- 1 farsight farsight 4096 May 6 19:39 a.txt
如何验证行缓冲的大小:
原理:同全缓冲的原理
例子:
#include <stdio.h> #include <unistd.h>
int main()
{
//当缓冲区中的数据<=1024,在没有其他强制刷新的情况下,不会
//清空缓冲区,只有当缓冲区中的数据>1024个字符时,才会刷新
int i = 0;
for(i = 0; i < 1024; i++)
{
fputc('a',stdout);
}
\_exit(0);
}
输出结果:
没有数据输出
#include <stdio.h>
#include <unistd.h>
int main() { //当缓冲区中的数据<=1024,在没有其他强制刷新的情况下,不会 //清空缓冲区,只有当缓冲区中的数据>1024个字符时,才会刷新 int i = 0; for(i = 0; i < 1030; i++) { fputc('a',stdout); } _exit(0); }
输出结果:写入1024个数据
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
无缓冲:
stderr
例子:
#include <stdio.h> #include <unistd.h>
int main()
{
int i = 0;
fputs("error 011",stderr);
\_exit(0);
}
输出: farsight@ubuntu:~/ioclass
如果想用其他方法来强制刷新缓冲区,有以下几种方法:
1.使用函数fflush
2.行缓冲中遇到’\n’
3.exit(),进程退出时
4.程序自动退出时(即,原因是3,进程自动退出)
5.fclose()调用时
6.正常return 0
如果想程序退出,且不刷新缓冲区:
1.使用\_exit()函数
============================================================================================
如果想要设置缓冲区的大小:
使用setvbuf()函数来实现:
/\*
\*函数名:setvbuf
\*函数功能:设置缓冲区大小
\*函数参数:
\* FILE \*stream:被设置缓冲区的文件流指针
\* char \*buf:缓冲区的首地址
\* int mode:
\* \_IONBF unbuffered(无缓冲)
\* \_IOLBF line buffered(行缓冲)
\* \_IOFBF fully buffered(全缓冲)
\*
\* size\_t size:缓冲区的大小(stdio.h有一个BUFSIZ宏,是8192)
\*函数返回值:int,成功返回0,失败返回错误码
\*/
int setvbuf(FILE \*stream, char \*buf, int mode, size\_t size);
如何获取缓冲:
1.当文件上发生第一个IO操作时,才会调用malloc
例子:
#include <stdio.h> #include <string.h> int main() {
char bufr[8192] = {0};
printf("BUFSIZ:%d\n",BUFSIZ);
FILE \*fp = NULL;
fp = fopen("a.txt", "r+");
if(NULL == fp)
{
puts("open stdout error.");
return -1;
}
char buf[20];
memset(buf, 0, sizeof(buf));
//读操作之前打印
printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
fread(buf, 1, sizeof(buf), fp);
puts(buf);
puts("=================");
printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
char str[] = "hellodlfjsdklffsdjflkdksfjlkdsfjlklkdksjfkl";
fwrite(buf, strlen(buf),1,fp);
//读写操作之后打印
printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
puts("&&&&&&&&&&&&&&&&&&&&&&&");
char \*p = NULL;
//通过setvbuf来重新设置缓冲区大小
setvbuf(fp,bufr,_IOFBF,BUFSIZ);
fseek(fp, 0L, SEEK\_SET);
memset(buf, 0, sizeof(buf));
printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
fclose(fp);
return 0;
}
代码输出:
farsight@ubuntu:~/ioclass$ ./a.out
BUFSIZ:8192
bufsize:0
readbufsize:0
writebufsize:0
aaaaaaaaaaaaaaaaaaaa
=================
readbufsize:4096
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新