[实践OK]为何数组的首地址当指针传入函数时,得传入数组的长度之sizeof函数,sizeof(数组名)和sizeof(指针)的区别,及fwrite里的第二第三参数的用法。
Unix/LinuxC技术 jackxiang 2018-2-22 09:02
背景:为何数组的首地址当指针传入函数时,得传入数组的长度?在函数体内的其实是通过数组名初始化的指针形参,故不能在函数中通过 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度。所以一般将数组名作为形参传入函数时,也会同时传递一个数组长度的参数。为何指针长度是8位,而不是4位?因为系统是64位的(8字节,64位系统)。
数组名一旦传入函数,再用sizeof(数组名,也就是首地址),其得出的值变为8了,不再是1024了,实践如下:
vi fwrite.c
#./fwrite
1)直接在变量申明段里访问数组长度值:sizeof的数组名buffer=1024
2)!!returnArrPointerLen函数返回buffer数组首地址到函数里后长度值就不等于1024了,等于:8
3)returnArrPointerLen函数传入指向数组buffer首地址返回buffer长度和申明数组长度不一样等于8
4)sizeof buf=8
5)strlen buf=44
6)sizeof buf=8
7)strlen buf=34
总之,一旦将数组首地址传入函数,那么其长度就变成了指针长度了,而32位系统和64位系统指针分别对应的是4和8:
#./sizeofarr
1)指向数组首地址,数组的长度是: 20
2)用指针指向数组的首地址长度是: 8
3)试图求下数组第一个键值的空间大小sizeof(number)=4
4)再试图通过sizeof(number)/sizeof(number[0]得出5? 5
数组的元素分别是:
1 2 3 4 5
在c/c++中我们一般都用 sizeof(数组名)/sizeof(数组元素类型) 来计算数组的长度,其中 sizeof(数组名) 计算的是数组占用的存储大小。同时,一般我们认为数组名和指针就是一回事,最近写程序时将数组名作为指针形参传入函数,想在函数中用 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度时却出了错,最后发现原来是sizeof(数组名)和sizeof(指针)的区别导致的,于是写了段代码测试了一下:
输出结果:
数组名:40
指针:8
指针引用:8
函数指针形参:8
可以看到,当sizeof的参数是数组名时,计算的是整个数组的存储大小;当sizeof的参数是指针时,计算的是指针的大小(8字节,64位系统)。而且,可以定义对指针的引用,但却不能用数组名来作为指针引用的右值,可见数组名和指针还是有区别的。同时,将数组名作为实参传入函数时,因为形参是指针,所以在函数体内的其实是通过数组名初始化的指针形参,故不能在函数中通过 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度。所以一般将数组名作为形参传入函数时,也会同时传递一个数组长度的参数。
来自:http://blog.csdn.net/u012707739/article/details/75732159
C语言fwrite怎么写入文件?
==================来自:https://zhidao.baidu.com/question/1893763120275364500.html==================
我设了一个字符串char rgb[3]; 然后用fwrite(&rgb,3,1,file)和fwrite(&rgb,1,3,file)写入一个bmp文件 这两个得到了相同的东西 而fwrite(&rgb,3,2,file)得到的是rgb的三个数据+三个CC(204) 请问fwrite是怎么读取rgb的数据的? 是不是按照首地址++? fwrite(&rgb,3,2,file)里前三个数读完了然后想要读取rgb[3] [4]和[5]但是读取的是乱码 所以默认显示为CC?
fwrite函数在写文件时是以二进制形式进行的。
函数原型:int fwrite(char *ptr, unsigned size, unsigned n, FILE *fp);
功 能:将ptr所指向的n*size个字节输出到fp所指向的文件中
返 回 值:写到fp文件中的数据项的个数
实践:
数组名一旦传入函数,再用sizeof(数组名,也就是首地址),其得出的值变为8了,不再是1024了,实践如下:
vi fwrite.c
#./fwrite
1)直接在变量申明段里访问数组长度值:sizeof的数组名buffer=1024
2)!!returnArrPointerLen函数返回buffer数组首地址到函数里后长度值就不等于1024了,等于:8
3)returnArrPointerLen函数传入指向数组buffer首地址返回buffer长度和申明数组长度不一样等于8
4)sizeof buf=8
5)strlen buf=44
6)sizeof buf=8
7)strlen buf=34
总之,一旦将数组首地址传入函数,那么其长度就变成了指针长度了,而32位系统和64位系统指针分别对应的是4和8:
#./sizeofarr
1)指向数组首地址,数组的长度是: 20
2)用指针指向数组的首地址长度是: 8
3)试图求下数组第一个键值的空间大小sizeof(number)=4
4)再试图通过sizeof(number)/sizeof(number[0]得出5? 5
数组的元素分别是:
1 2 3 4 5
在c/c++中我们一般都用 sizeof(数组名)/sizeof(数组元素类型) 来计算数组的长度,其中 sizeof(数组名) 计算的是数组占用的存储大小。同时,一般我们认为数组名和指针就是一回事,最近写程序时将数组名作为指针形参传入函数,想在函数中用 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度时却出了错,最后发现原来是sizeof(数组名)和sizeof(指针)的区别导致的,于是写了段代码测试了一下:
输出结果:
数组名:40
指针:8
指针引用:8
函数指针形参:8
可以看到,当sizeof的参数是数组名时,计算的是整个数组的存储大小;当sizeof的参数是指针时,计算的是指针的大小(8字节,64位系统)。而且,可以定义对指针的引用,但却不能用数组名来作为指针引用的右值,可见数组名和指针还是有区别的。同时,将数组名作为实参传入函数时,因为形参是指针,所以在函数体内的其实是通过数组名初始化的指针形参,故不能在函数中通过 sizeof(指针形参)/sizeof(数组元素类型) 来计算数组长度。所以一般将数组名作为形参传入函数时,也会同时传递一个数组长度的参数。
来自:http://blog.csdn.net/u012707739/article/details/75732159
C语言fwrite怎么写入文件?
==================来自:https://zhidao.baidu.com/question/1893763120275364500.html==================
我设了一个字符串char rgb[3]; 然后用fwrite(&rgb,3,1,file)和fwrite(&rgb,1,3,file)写入一个bmp文件 这两个得到了相同的东西 而fwrite(&rgb,3,2,file)得到的是rgb的三个数据+三个CC(204) 请问fwrite是怎么读取rgb的数据的? 是不是按照首地址++? fwrite(&rgb,3,2,file)里前三个数读完了然后想要读取rgb[3] [4]和[5]但是读取的是乱码 所以默认显示为CC?
fwrite函数在写文件时是以二进制形式进行的。
函数原型:int fwrite(char *ptr, unsigned size, unsigned n, FILE *fp);
功 能:将ptr所指向的n*size个字节输出到fp所指向的文件中
返 回 值:写到fp文件中的数据项的个数
实践:
[实践OK]父进程退出后如何通知子进程退出,主进程退出对子线程的影响?ps -f -C sudo 和 ps -f -C multepoolser,ps axjf|less再输入左斜杠后输入cron,pstree。
Unix/LinuxC技术 jackxiang 2018-2-19 15:13
背景:主进程退出后,子进程没有退出,http://jackxiang.com/post/6937/
父进程退出后,子进程还在,怎么杀死,暂别说平滑过渡死,先杀死子进程得了,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。用了prctl 这个调用,实践来自@http://blog.csdn.net/gavin_new/article/details/73432013:
1)子进程加上在子进程中给父进程设置当父进程退出时子进程收到的信号:
/* 子进程中给父进程设置当父进程退出时子进程收到的信号 */
prctl(PR_SET_PDEATHSIG, SIGHUP);
2)主进程退出退知子进程的信号量执行:
if (sig == SIGHUP){
printf("child recv SIGHUP..\n");//主进程退出退知子进程
//kill_signal_master(sig); //不要这行也成,&kill_signal_worker部分应该作了处理。
}
3)实践是否真杀死了?
#ps -f -C multepoolser
UID PID PPID C STIME TTY TIME CMD
root 14096 13713 0 15:58 pts/1 00:00:00 [httpmut: master process] master process
apache 14097 14096 99 15:58 pts/1 00:00:02 [httpmut: worker process] worker process
#kill -TERM 14096
#ps -f -C multepoolser #子进程也被杀死退出了。
UID PID PPID C STIME TTY TIME CMD
========================具体代码=========================
httpmut父进程处理kill信号:
处理函数:
子进程线号处理侦听函数:
子进程信号处理:
Linux 中创建子进程是相当方便的,通过fork调用即可。当子进程退出时,要给父进程发送SIG_CHLD信号,是为了父进程回收子进程的资源,方便管理的目的。 但是当父进程退出后,一般是不会通知子进程的,父进程会将自己的所有子进程过继给init进程。
但是,在实际的项目中,我们有这样的需求: 如果父进程退出后,希望能通知子进程退出。
我们知道,可以利用进程间通信机制,在父进程退出前主动发送信号或pipe或其他手段告知子进程自己退出了。
但是,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。
这时怎么办呢?
我们发现 prctl 这个调用, 通过man prctl:
据此, 我们可以在子进程中给父进程设置当父进程退出时子进程收到的信号。
代码如下:
通过测试,如果去掉 prctl调用,当父进程发生段错误退出后,子进程依然继续运行。 如果去掉signal调用,即子进程不捕获SIG_HUP信号,当父进程退出后依然会退出,只是退出的有些不优雅罢了。
来自:http://blog.csdn.net/gavin_new/article/details/73432013
实践如下:
#./prctl
in parent.
in child...
memcpy ...
child recv SIGHUP..
in child...
child exit...
段错误(吐核)
二、主进程退出对子线程的影响,线程退出是什么样的一个情况呢?源码来自:http://originlee.com/2015/04/08/influence-of-main-threads-exiting-to-child-thread/
cat ./pthreadtest.c
gcc -o pthreadtest pthreadtest.c -lpthread -lmemcached
#./pthreadtest
child loops
child loops
child loops
child loops
child loops
...
child loops
child loops
child loops
main exit
运行上面的代码,会发现程序在打印一定数量的「child loops」和一句「main exit」之后退出,并且在退出之前的最后一句打印是「main exit」。
按照他们的逻辑,你看,因为主线程在打印完「main exit」后退出了,然后子线程也跟着退出了,所以随后就没有子线程的打印了。
但其实这里是混淆了进程退出和线程退出的概念了。实际的情况是主线程中的main函数执行完ruturn后弹栈,然后调用glibc库函数exit,exit进行相关清理工作后调用_exit系统调用退出该进程。所以,这种情况实际上是因为进程运行完毕退出导致所有的线程也都跟着退出了,并非是因为主线程的退出导致子线程也退出。
Linux线程模型
实际上,posix线程和一般的进程不同,在概念上没有主线程和子线程之分(虽然在实际实现上还是有一些区分),如果仔细观察apue或者unp等书会发现基本看不到「主线程」或者「子线程」等词语,在csapp中甚至都是用「对等线程」一词来描述线程间的关系。
在Linux 2.6以后的posix线程都是由用户态的pthread库来实现的。在使用pthread库以后,在用户视角看来,每一个tast_struct就对应一个线程(tast_struct原本是内核对应一个进程的结构),而一组线程以及他们所共同引用的一组资源就是进程。从Linux 2.6开始,内核有了线程组的概念,tast_struct结构中增加了一个tgid(thread group id)字段。getpid(获取进程号)通过系统调用返回的也是tast_struct中的tgid,所以tgid其实就是进程号。而tast_struct中的线程号pid字段则由系统调用syscall(SYS_gettid)来获取。
当线程收到一个kill致命信号时,内核会将处理动作施加到整个线程组上。为了应付「发送给进程的信号」和「发送给线程的信号」,tast_struct里面维护了两套signal_pending,一套是线程组共用的,一套是线程独有的。通过kill发送的致命信号被放在线程组共享的signal_pending中,可以任意由一个线程来处理。而通过pthread_kill发送的信号被放在线程独有的signal_pending中,只能由本线程来处理。
关于线程与信号,apue有这么几句:
每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的。这意味着尽管单个线程可以阻止某些信号,但当线程修改了与某个信号相关的处理行为以后,所有的线程都必须共享这个处理行为的改变。这样如果一个线程选择忽略某个信号,而其他的线程可以恢复信号的默认处理行为,或者是为信号设置一个新的处理程序,从而可以撤销上述线程的信号选择。
如果信号的默认处理动作是终止该进程,那么把信号传递给某个线程仍然会杀掉整个进程。
例如一个程序a.out创建了一个子线程,假设主线程的线程号为9601,子线程的线程号为9602(它们的tgid都是9601),因为默认没有设置信号处理程序,所以如果运行命令kill 9602的话,是可以把9601和9602这个两个线程一起杀死的。如果不知道Linux线程背后的故事,可能就会觉得遇到灵异事件了。
另外系统调用syscall(SYS_gettid)获取的线程号与pthread_self获取的线程号是不同的,pthread_self获取的线程号仅仅在线程所依赖的进程内部唯一,在pthread_self的man page中有这样一段话:
Thread IDs are guaranteed to be unique only within a process. A thread ID may be reused after a terminated thread has been joined, or a detached thread has terminated.
所以在内核中唯一标识线程ID的线程号只能通过系统调用syscall(SYS_gettid)获取。
父进程退出后,子进程还在,怎么杀死,暂别说平滑过渡死,先杀死子进程得了,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。用了prctl 这个调用,实践来自@http://blog.csdn.net/gavin_new/article/details/73432013:
1)子进程加上在子进程中给父进程设置当父进程退出时子进程收到的信号:
/* 子进程中给父进程设置当父进程退出时子进程收到的信号 */
prctl(PR_SET_PDEATHSIG, SIGHUP);
2)主进程退出退知子进程的信号量执行:
if (sig == SIGHUP){
printf("child recv SIGHUP..\n");//主进程退出退知子进程
//kill_signal_master(sig); //不要这行也成,&kill_signal_worker部分应该作了处理。
}
3)实践是否真杀死了?
#ps -f -C multepoolser
UID PID PPID C STIME TTY TIME CMD
root 14096 13713 0 15:58 pts/1 00:00:00 [httpmut: master process] master process
apache 14097 14096 99 15:58 pts/1 00:00:02 [httpmut: worker process] worker process
#kill -TERM 14096
#ps -f -C multepoolser #子进程也被杀死退出了。
UID PID PPID C STIME TTY TIME CMD
========================具体代码=========================
httpmut父进程处理kill信号:
处理函数:
子进程线号处理侦听函数:
子进程信号处理:
Linux 中创建子进程是相当方便的,通过fork调用即可。当子进程退出时,要给父进程发送SIG_CHLD信号,是为了父进程回收子进程的资源,方便管理的目的。 但是当父进程退出后,一般是不会通知子进程的,父进程会将自己的所有子进程过继给init进程。
但是,在实际的项目中,我们有这样的需求: 如果父进程退出后,希望能通知子进程退出。
我们知道,可以利用进程间通信机制,在父进程退出前主动发送信号或pipe或其他手段告知子进程自己退出了。
但是,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。
这时怎么办呢?
我们发现 prctl 这个调用, 通过man prctl:
据此, 我们可以在子进程中给父进程设置当父进程退出时子进程收到的信号。
代码如下:
通过测试,如果去掉 prctl调用,当父进程发生段错误退出后,子进程依然继续运行。 如果去掉signal调用,即子进程不捕获SIG_HUP信号,当父进程退出后依然会退出,只是退出的有些不优雅罢了。
来自:http://blog.csdn.net/gavin_new/article/details/73432013
实践如下:
#./prctl
in parent.
in child...
memcpy ...
child recv SIGHUP..
in child...
child exit...
段错误(吐核)
二、主进程退出对子线程的影响,线程退出是什么样的一个情况呢?源码来自:http://originlee.com/2015/04/08/influence-of-main-threads-exiting-to-child-thread/
cat ./pthreadtest.c
gcc -o pthreadtest pthreadtest.c -lpthread -lmemcached
#./pthreadtest
child loops
child loops
child loops
child loops
child loops
...
child loops
child loops
child loops
main exit
运行上面的代码,会发现程序在打印一定数量的「child loops」和一句「main exit」之后退出,并且在退出之前的最后一句打印是「main exit」。
按照他们的逻辑,你看,因为主线程在打印完「main exit」后退出了,然后子线程也跟着退出了,所以随后就没有子线程的打印了。
但其实这里是混淆了进程退出和线程退出的概念了。实际的情况是主线程中的main函数执行完ruturn后弹栈,然后调用glibc库函数exit,exit进行相关清理工作后调用_exit系统调用退出该进程。所以,这种情况实际上是因为进程运行完毕退出导致所有的线程也都跟着退出了,并非是因为主线程的退出导致子线程也退出。
Linux线程模型
实际上,posix线程和一般的进程不同,在概念上没有主线程和子线程之分(虽然在实际实现上还是有一些区分),如果仔细观察apue或者unp等书会发现基本看不到「主线程」或者「子线程」等词语,在csapp中甚至都是用「对等线程」一词来描述线程间的关系。
在Linux 2.6以后的posix线程都是由用户态的pthread库来实现的。在使用pthread库以后,在用户视角看来,每一个tast_struct就对应一个线程(tast_struct原本是内核对应一个进程的结构),而一组线程以及他们所共同引用的一组资源就是进程。从Linux 2.6开始,内核有了线程组的概念,tast_struct结构中增加了一个tgid(thread group id)字段。getpid(获取进程号)通过系统调用返回的也是tast_struct中的tgid,所以tgid其实就是进程号。而tast_struct中的线程号pid字段则由系统调用syscall(SYS_gettid)来获取。
当线程收到一个kill致命信号时,内核会将处理动作施加到整个线程组上。为了应付「发送给进程的信号」和「发送给线程的信号」,tast_struct里面维护了两套signal_pending,一套是线程组共用的,一套是线程独有的。通过kill发送的致命信号被放在线程组共享的signal_pending中,可以任意由一个线程来处理。而通过pthread_kill发送的信号被放在线程独有的signal_pending中,只能由本线程来处理。
关于线程与信号,apue有这么几句:
每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的。这意味着尽管单个线程可以阻止某些信号,但当线程修改了与某个信号相关的处理行为以后,所有的线程都必须共享这个处理行为的改变。这样如果一个线程选择忽略某个信号,而其他的线程可以恢复信号的默认处理行为,或者是为信号设置一个新的处理程序,从而可以撤销上述线程的信号选择。
如果信号的默认处理动作是终止该进程,那么把信号传递给某个线程仍然会杀掉整个进程。
例如一个程序a.out创建了一个子线程,假设主线程的线程号为9601,子线程的线程号为9602(它们的tgid都是9601),因为默认没有设置信号处理程序,所以如果运行命令kill 9602的话,是可以把9601和9602这个两个线程一起杀死的。如果不知道Linux线程背后的故事,可能就会觉得遇到灵异事件了。
另外系统调用syscall(SYS_gettid)获取的线程号与pthread_self获取的线程号是不同的,pthread_self获取的线程号仅仅在线程所依赖的进程内部唯一,在pthread_self的man page中有这样一段话:
Thread IDs are guaranteed to be unique only within a process. A thread ID may be reused after a terminated thread has been joined, or a detached thread has terminated.
所以在内核中唯一标识线程ID的线程号只能通过系统调用syscall(SYS_gettid)获取。
git pull #出现:please enter a commit message to explain why this merge is necessary 请输入一个提交消息来解释为什么这个合并是必要的
Merge made by the 'recursive' strategy.
...277\220\347\273\264\346\211\213\345\206\214.md" | 23 ++++------------------
1 file changed, 4 insertions(+), 19 deletions(-)
阅读全文
Merge made by the 'recursive' strategy.
...277\220\347\273\264\346\211\213\345\206\214.md" | 23 ++++------------------
1 file changed, 4 insertions(+), 19 deletions(-)
阅读全文
[实践OK]FreeBSD 使用手冊之Virtual Consoles 和終端機
Unix/LinuxC技术 jackxiang 2018-2-13 10:09
背景:ps -ef|grep tty,出现很多tttyv进程,而有什么用呢?和Linux的不大一样,但又有点一样的,最扣只剩下一个ttyv0 "/usr/libexec/getty Pc" xterm on secure,其余均给关掉,VPS服务器本来内存就少,少一个 进程少点资源占用。
一、发现现象:
二、编辑配置:/etc/ttys文件,vi /etc/ttys ,也就是ttyv0外的,tty1-->tty7都是FreeBSD/i386 (pc3.example.org) (ttyv0),也就是默认就是ttyv0,而其它虚拟终端,FreeBSD 保留了特別的按鍵組合來切換 console,得用 Alt-F1、 Alt-F2、到 Alt-F8來切換 FreeBSD 的不同 console,对于云主机来讲除开查一些登录不了(启动不了,或运程登录不上去)疑难问题外,没有啥鸟用,但有时可能还真有用。
三、关掉没有用的(云主机,虚拟终端ttv0外基本上没有用)重新启动:
重新读取/etc/ttys来强制init对/etc/ttys文件做一个必要的修改后,你必须发送一个SIGHUP信号给初始化进程来迫使它重新读取配置文件,例如:
# kill -HUP 1
注意:init总是系统运行时的第一个进程,因此它总是PID 1。
如果能够正确设置,所有的线缆都是适当的,终端将可以启用了,然后一个getty进程将在每个终端运行,你将在你的终端上看到登陆命令行。
对于终端,init会在每个配置串口上为每个拨入连接产生一个getty进程。例如,如果一个modem被附带在/dev/ttyv1中,用命令ps ax可以显示下面这些:
#ps ax|grep ttyv
2929 v0 Is+ 0:00.00 /usr/libexec/getty Pc ttyv0
2930 v1 Is+ 0:00.00 /usr/libexec/getty Pc ttyv1
2931 v2 Is+ 0:00.00 /usr/libexec/getty Pc ttyv2
2932 v3 Is+ 0:00.00 /usr/libexec/getty Pc ttyv3
2933 v4 Is+ 0:00.00 /usr/libexec/getty Pc ttyv4
2934 v5 Is+ 0:00.00 /usr/libexec/getty Pc ttyv5
2935 v6 Is+ 0:00.00 /usr/libexec/getty Pc ttyv6
2936 v7 Is+ 0:00.00 /usr/libexec/getty Pc ttyv7
实践如下,留下两个ttyv0,ttyv1,其余都off掉:
(1)ttyv2到ttyv7全部off掉,修改/etc/ttys:
(2)#kill -HUP 1 ,发送一个SIGHUP信号给初始化进程来迫使它重新读取/etc/ttys配置文件。
(3)再看就只有俩了:
#ps -ef|grep tty
2929 v0 Is+ 0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv0
2930 v1 Is+ 0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv1
四、学习资料来自:ftp://ftp.uwc.ac.za/FOSS/freebsdcvs/www/data/doc/zh_TW/books/handbook/consoles.html
阅读全文
一、发现现象:
二、编辑配置:/etc/ttys文件,vi /etc/ttys ,也就是ttyv0外的,tty1-->tty7都是FreeBSD/i386 (pc3.example.org) (ttyv0),也就是默认就是ttyv0,而其它虚拟终端,FreeBSD 保留了特別的按鍵組合來切換 console,得用 Alt-F1、 Alt-F2、到 Alt-F8來切換 FreeBSD 的不同 console,对于云主机来讲除开查一些登录不了(启动不了,或运程登录不上去)疑难问题外,没有啥鸟用,但有时可能还真有用。
三、关掉没有用的(云主机,虚拟终端ttv0外基本上没有用)重新启动:
重新读取/etc/ttys来强制init对/etc/ttys文件做一个必要的修改后,你必须发送一个SIGHUP信号给初始化进程来迫使它重新读取配置文件,例如:
# kill -HUP 1
注意:init总是系统运行时的第一个进程,因此它总是PID 1。
如果能够正确设置,所有的线缆都是适当的,终端将可以启用了,然后一个getty进程将在每个终端运行,你将在你的终端上看到登陆命令行。
对于终端,init会在每个配置串口上为每个拨入连接产生一个getty进程。例如,如果一个modem被附带在/dev/ttyv1中,用命令ps ax可以显示下面这些:
#ps ax|grep ttyv
2929 v0 Is+ 0:00.00 /usr/libexec/getty Pc ttyv0
2930 v1 Is+ 0:00.00 /usr/libexec/getty Pc ttyv1
2931 v2 Is+ 0:00.00 /usr/libexec/getty Pc ttyv2
2932 v3 Is+ 0:00.00 /usr/libexec/getty Pc ttyv3
2933 v4 Is+ 0:00.00 /usr/libexec/getty Pc ttyv4
2934 v5 Is+ 0:00.00 /usr/libexec/getty Pc ttyv5
2935 v6 Is+ 0:00.00 /usr/libexec/getty Pc ttyv6
2936 v7 Is+ 0:00.00 /usr/libexec/getty Pc ttyv7
实践如下,留下两个ttyv0,ttyv1,其余都off掉:
(1)ttyv2到ttyv7全部off掉,修改/etc/ttys:
(2)#kill -HUP 1 ,发送一个SIGHUP信号给初始化进程来迫使它重新读取/etc/ttys配置文件。
(3)再看就只有俩了:
#ps -ef|grep tty
2929 v0 Is+ 0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv0
2930 v1 Is+ 0:00.00 TERM=xterm /usr/libexec/getty Pc ttyv1
四、学习资料来自:ftp://ftp.uwc.ac.za/FOSS/freebsdcvs/www/data/doc/zh_TW/books/handbook/consoles.html
阅读全文
Context Switches上下文切换性能详解
Unix/LinuxC技术 jackxiang 2018-2-11 16:41
[实践OK]FreeBSD 添加PATH环境变量~
Unix/LinuxC技术 jackxiang 2018-2-11 15:34
用Cshell:
echo $shell
/bin/csh
添加PATH:
vi ~/.cshrc
注意,$PATH放在最后面,否则会报错,Bad : modifier in $ '/'. ,Linux不存在这个问题:
setenv PATH $PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/mysql/bin
Welcome to jackxiang's Compute Service !
Bad : modifier in $ '/'.
参考:https://stackoverflow.com/questions/27021663/changing-the-path-variable-on-freebsd
这个没有试过:http://shanchao7932297.blog.163.com/blog/static/136362420109935248893/
echo $shell
/bin/csh
添加PATH:
vi ~/.cshrc
注意,$PATH放在最后面,否则会报错,Bad : modifier in $ '/'. ,Linux不存在这个问题:
setenv PATH $PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/mysql/bin
Welcome to jackxiang's Compute Service !
Bad : modifier in $ '/'.
参考:https://stackoverflow.com/questions/27021663/changing-the-path-variable-on-freebsd
这个没有试过:http://shanchao7932297.blog.163.com/blog/static/136362420109935248893/
以root用户运行最后的命令
Unix/LinuxC技术 jackxiang 2018-2-11 12:35
linux:
xiangdong登陆
ls /root
权限不够,运行:
sudo !!
列出root家目录内容。
记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
xiangdong登陆
ls /root
权限不够,运行:
sudo !!
列出root家目录内容。
记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
以root用户运行最后的命令
Unix/LinuxC技术 jackxiang 2018-2-11 12:35
linux:
xiangdong登陆
ls /root
权限不够,运行:
sudo !!
列出root家目录内容。
记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
xiangdong登陆
ls /root
权限不够,运行:
sudo !!
列出root家目录内容。
记录命令行会话:
script命令,保存到typescript:script文件,输入一堆后,在输入exit,也就会保存到文件里面去。
[实践OK][FreeBSD] 修改系統時間 UTC->CST,FREEBSD时间设置与时区设置教程,及PHP 5.6.33下Owncloud错误日志error_log少了8小时的问题排查。
Unix/LinuxC技术 jackxiang 2018-2-11 11:32
总结:本质上是因为PHP的应用程序Owncloud他自己的设置引起了PHP的应用日志时间少了8小时,而PHP的设置 是没有毛病的,如下:
./lib/base.php: date_default_timezone_set('UTC'); ##修改为:date_default_timezone_set('Etc/GMT-8');
=================================================================================
零、系统时间正确:
date
Sun Feb 11 11:30:16 CST 2018
UTC----全球标准时间指的是由世界时间标准设定的时间。原先也被称为格林威治标准时间或者 GMT
CST----CMOS时间,即本机的时间!
PHP.ini里也配置了:date.timezone = Asia/Shanghai:
在php.ini中设置date.timezone的值为PRC,设置好以后的为:date.timezone=PRC或者date.timezone = Asia/Shanghai,同时取消这一行代码的注释,即去掉前面的分号就可以了。
/usr/local/php/etc/php-fpm.conf里,同样两个日志时间不对:
一、应用错误日志少了8小时:
php-fpm.conf
php_admin_value[error_log] = /data/logs/php/php-www-error.log
/data/logs/php/php-www-error.log
[11-Feb-2018 02:58:53 UTC] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
二、这个php-fpm-error日志和系统时间保持一致:
[global]
error_log = /data/logs/php/php-fpm-error.log
这个是对的:
/data/logs/php/php-fpm-error.log <==
[11-Feb-2018 10:58:37] WARNING: [pool www] server reached pm.max_children setting (6), consider raising it
刚开始认为是FreeBSD的时区问题,但实际上不是它的问题,如下:
FreeBSD 11.1 PHP日志出现:
[11-Feb-2018 03:06:39 UTC] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
系统时间:date
Sun Feb 11 11:18:57 CST 2018
因为刚安装系统是使用UTC时间,所以安装系统后,需要设置回上海时区!操作需要root权限!
#adjkerntz -a 调节COMS时间
#date
时间相差8小时,
可能是一个Bug:https://bugs.php.net/bug.php?id=60723 ,但是是 很多年前了,我这都PHP 5.6.33 (cli) (built: Feb 11 2018 10:42:42) ,不存在,后来也证明是Owncloud代码的问题。
http://bbs.csdn.net/topics/390091176里说:php_errors.log (/data/logs/php/php-www-error.log)人家打的是gmtime,你系统时间是localtime,差8小时是正确的,你得想办法配置php_errors.log输出的是localtime就和系统时间一致了,懂吗。
原来是Owncloud是老外做的,设置的date_default_timezone_set可能不一样导致:
#grep -r "date_default_timezone_set" ./
./3rdparty/sabre/vobject/lib/TimeZoneUtil.php: * (as configured using date_default_timezone_set, or the date.timezone ini
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php: date_default_timezone_set('UTC');
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php: date_default_timezone_set($oldTZ);
./apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php:date_default_timezone_set('UTC');
./apps/files_texteditor/js/vendor/ace/src-noconflict/mode-php.js: 'date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|' +
./lib/base.php: date_default_timezone_set('UTC'); ##修改为:date_default_timezone_set('Etc/GMT-8');
成功修复:
手动修改后就OK了,就是PHP代码上作了修改引起的!!!
[11-Feb-2018 11:44:32 Etc/GMT-8] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
灵感来源,下面代码的日志时间正确,date_default_timezone_set('Etc/GMT-8'); //设置时区,这块有关系,于是查Owncloud是否一样?果然不一样,修改了再测试就发现Owncloud对了:
error.class.php
a.php
产生错误时间正确:
[11-Feb-2018 11:39:08 Asia/Shanghai] 2018-02-11 11:39:08 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice: Undefined index: aaaaadfa in /data/www/comm.jackxiang.com/a.php on line 4
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice: Undefined variable: _SESSION in /data/www/comm.jackxiang.com/a.php on line 5
[11-Feb-2018 11:41:59 Asia/Shanghai] 2018-02-11 11:41:59 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5
关于这个date_default_timezone_set的一些时间值列表:来自@https://zhidao.baidu.com/question/383369268.html
date_default_timezone_set("Etc/GMT").:是格林威治标准时间,得到的时间和默认时区是一样的
ate_default_timezone_set("Etc/GMT+8");比林威治标准时间慢8小时,
date_default_timezone_set("Etc/GMT-8");东八区,我们比那快8小时所以减8
或者使用:date_default_timezone_set('PRC')设置中国时区
最后,更多关于FreeBSD的时间设置知识:
---------------------------------------------[FreeBSD] 修改系統時間 UTC->CST------------------------------------------------------------
剛安裝好系統是屬於格林時間,所以去設定一下如何弄回去内地 GMT+8 的時間
有2種方式~一個用圖形介面:
1、#tzsetup
是一個不錯的 timezone 設定工具 , 進去之後選擇 5.Asia -> ShangHai
2、另一個方法是:
#cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
#adjkerntz -a
#date
#Sat Jun 23 10:50:40 CST 200
ps:(adjkerntz = adjust kernal timezone)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/1808/showart_492283.html
来自:https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html
最近手上弄了台FreeBSD系统的VPS,因为系统无法更换,所以就只能用这么用着了,第一次配置的时候记得配置了时区,可是仍旧显示不正确。这样子看系统日志的时候就不是太方便,因为时间老是不对,虽然这台服务器打算是专门做SSH代×理滴,需要滴联系奶牛哈~~~点此联系
下面说说设置,首先要进入一个root shell
#sysinstall
依次进入 configure→Time Zone→UTC = no→ Asia → China→ Beijing,Guangdong,Shanghai etc.
Does the abbreviation `CST’ look reasonable? = OK
提示选择yes,然后退出sysinstall就可以了。
查看日期的命令是data
同步时间的命令是 ntpdate nist1.symmetricom.com
参考:http://www.nenew.net/freebsd-time-zone-setting.html
https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html
./lib/base.php: date_default_timezone_set('UTC'); ##修改为:date_default_timezone_set('Etc/GMT-8');
=================================================================================
零、系统时间正确:
date
Sun Feb 11 11:30:16 CST 2018
UTC----全球标准时间指的是由世界时间标准设定的时间。原先也被称为格林威治标准时间或者 GMT
CST----CMOS时间,即本机的时间!
PHP.ini里也配置了:date.timezone = Asia/Shanghai:
在php.ini中设置date.timezone的值为PRC,设置好以后的为:date.timezone=PRC或者date.timezone = Asia/Shanghai,同时取消这一行代码的注释,即去掉前面的分号就可以了。
/usr/local/php/etc/php-fpm.conf里,同样两个日志时间不对:
一、应用错误日志少了8小时:
php-fpm.conf
php_admin_value[error_log] = /data/logs/php/php-www-error.log
/data/logs/php/php-www-error.log
[11-Feb-2018 02:58:53 UTC] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
二、这个php-fpm-error日志和系统时间保持一致:
[global]
error_log = /data/logs/php/php-fpm-error.log
这个是对的:
/data/logs/php/php-fpm-error.log <==
[11-Feb-2018 10:58:37] WARNING: [pool www] server reached pm.max_children setting (6), consider raising it
刚开始认为是FreeBSD的时区问题,但实际上不是它的问题,如下:
FreeBSD 11.1 PHP日志出现:
[11-Feb-2018 03:06:39 UTC] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
系统时间:date
Sun Feb 11 11:18:57 CST 2018
因为刚安装系统是使用UTC时间,所以安装系统后,需要设置回上海时区!操作需要root权限!
#adjkerntz -a 调节COMS时间
#date
时间相差8小时,
可能是一个Bug:https://bugs.php.net/bug.php?id=60723 ,但是是 很多年前了,我这都PHP 5.6.33 (cli) (built: Feb 11 2018 10:42:42) ,不存在,后来也证明是Owncloud代码的问题。
http://bbs.csdn.net/topics/390091176里说:php_errors.log (/data/logs/php/php-www-error.log)人家打的是gmtime,你系统时间是localtime,差8小时是正确的,你得想办法配置php_errors.log输出的是localtime就和系统时间一致了,懂吗。
原来是Owncloud是老外做的,设置的date_default_timezone_set可能不一样导致:
#grep -r "date_default_timezone_set" ./
./3rdparty/sabre/vobject/lib/TimeZoneUtil.php: * (as configured using date_default_timezone_set, or the date.timezone ini
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php: date_default_timezone_set('UTC');
./3rdparty/mcnetic/zipstreamer/src/ZipStreamer.php: date_default_timezone_set($oldTZ);
./apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php:date_default_timezone_set('UTC');
./apps/files_texteditor/js/vendor/ace/src-noconflict/mode-php.js: 'date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|' +
./lib/base.php: date_default_timezone_set('UTC'); ##修改为:date_default_timezone_set('Etc/GMT-8');
成功修复:
手动修改后就OK了,就是PHP代码上作了修改引起的!!!
[11-Feb-2018 11:44:32 Etc/GMT-8] PHP Fatal error: Allowed memory size of 18874368 bytes exhausted (tried to allocate 2048 bytes) in /data/www/xdxp.cn/lib/private/preview/txt.php on line 60
灵感来源,下面代码的日志时间正确,date_default_timezone_set('Etc/GMT-8'); //设置时区,这块有关系,于是查Owncloud是否一样?果然不一样,修改了再测试就发现Owncloud对了:
error.class.php
a.php
产生错误时间正确:
[11-Feb-2018 11:39:08 Asia/Shanghai] 2018-02-11 11:39:08 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice: Undefined index: aaaaadfa in /data/www/comm.jackxiang.com/a.php on line 4
[11-Feb-2018 11:41:59 Asia/Shanghai] PHP Notice: Undefined variable: _SESSION in /data/www/comm.jackxiang.com/a.php on line 5
[11-Feb-2018 11:41:59 Asia/Shanghai] 2018-02-11 11:41:59 运行时提示(E_NOTICE) Undefined variable: _SESSION /data/www/comm.jackxiang.com/a.php 5
关于这个date_default_timezone_set的一些时间值列表:来自@https://zhidao.baidu.com/question/383369268.html
date_default_timezone_set("Etc/GMT").:是格林威治标准时间,得到的时间和默认时区是一样的
ate_default_timezone_set("Etc/GMT+8");比林威治标准时间慢8小时,
date_default_timezone_set("Etc/GMT-8");东八区,我们比那快8小时所以减8
或者使用:date_default_timezone_set('PRC')设置中国时区
最后,更多关于FreeBSD的时间设置知识:
---------------------------------------------[FreeBSD] 修改系統時間 UTC->CST------------------------------------------------------------
剛安裝好系統是屬於格林時間,所以去設定一下如何弄回去内地 GMT+8 的時間
有2種方式~一個用圖形介面:
1、#tzsetup
是一個不錯的 timezone 設定工具 , 進去之後選擇 5.Asia -> ShangHai
2、另一個方法是:
#cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
#adjkerntz -a
#date
#Sat Jun 23 10:50:40 CST 200
ps:(adjkerntz = adjust kernal timezone)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/1808/showart_492283.html
来自:https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html
最近手上弄了台FreeBSD系统的VPS,因为系统无法更换,所以就只能用这么用着了,第一次配置的时候记得配置了时区,可是仍旧显示不正确。这样子看系统日志的时候就不是太方便,因为时间老是不对,虽然这台服务器打算是专门做SSH代×理滴,需要滴联系奶牛哈~~~点此联系
下面说说设置,首先要进入一个root shell
#sysinstall
依次进入 configure→Time Zone→UTC = no→ Asia → China→ Beijing,Guangdong,Shanghai etc.
Does the abbreviation `CST’ look reasonable? = OK
提示选择yes,然后退出sysinstall就可以了。
查看日期的命令是data
同步时间的命令是 ntpdate nist1.symmetricom.com
参考:http://www.nenew.net/freebsd-time-zone-setting.html
https://www.west.cn/info/html/caozuoxitong/FreeBSD/20090513/132105.html
[实践OK] Mac使用之查看二进制,Linux vim 查看16进制之:%!xxd,Linux下用 od -cx filename和xxd 查看文件十六进制编码
Unix/LinuxC技术 jackxiang 2018-2-9 14:40
mac下想查看十六进制文件,发现winhex没有mac版本(http://www.haote.com/xz/594902.html),但是搜到了 Hex Fiend,也非常棒,哈哈哈。
轻量级,免费,perfect~
下载地址:http://ridiculousfish.com/hexfiend/
Linux vim 查看16进制之:%!xxd
00000c0: 4163 4371 4553 532d 2d0d 0a AcCqESS--..
想得到16进制和ascii码对应的显示结果,可以添加 -C参数
xxd查看文件编码:
xxd gbk.php
0000000: 3c3f 7068 700a 2020 7661 725f 6475 6d70 <?php. var_dump
0000010: 2862 696e 3268 6578 2822 b6ab 2229 293b (bin2hex(".."));
0000020: 0a .
1. 在 vi 或 vim 的命令状态下
:%!xxd ——将当前文本转换为16进制格式。
:%!xxd -r ——将当前文件转换回文本格式。
2. od - dump files in octal and other formats
顾名思义是查看八进制,可以通过指定参数为查看十六进制
-A 指定左边侧栏显示的地址基数,默认为八进制
-t 指定输出单元的进制格式和字节数
-x = -t x2 输出单元为双字节(注意:每单元内排列顺序从左到右为 [高字节|低字节])
Linux指令:od
示例用法:od -c hello
Linux指令:od
od命令
用户通常使用od命令查看特殊格式的文件内容。通过指定该命令的不同选项可以以十进制、八进制、十六进制和ASCII码来显示文件。
语法:od [选项] 文件…
命令中各选项的含义:
- A 指定地址基数,包括:
d 十进制
o 八进制(系统默认值)
x 十六进制
n 不打印位移值
- t 指定数据的显示格式,主要的参数有:
c ASCII字符或反斜杠序列
来自:http://blog.csdn.net/dumgeewang/article/details/7778143
http://blog.csdn.net/chenglian_999/article/details/4672177
=========================================
主要用来查看下换行符号:
#od -c S.txt
0000000 1 1 1 1 * 1 + 2 2 2 + 5 * 1 1 +
0000020 8 * 7 7 \n \n
0000026
#od -c S.txt
0000000 1 1 1 1 * 1 + 2 2 2 + 5 * 1 1 +
0000020 8 * 7 7 \n
0000025
===============Q:=========================
cat S.txt
11+2
od -c S.txt
0000000 1 1 + 2
0000004
-------------------------------------------------------------------------------
bc没有换行,cat filename |bc 会提示:
cat S.txt|bc
bc: stdin:1: syntax error: unexpected EOF
也就是说,还得有一个结尾换行符号。
轻量级,免费,perfect~
下载地址:http://ridiculousfish.com/hexfiend/
Linux vim 查看16进制之:%!xxd
00000c0: 4163 4371 4553 532d 2d0d 0a AcCqESS--..
想得到16进制和ascii码对应的显示结果,可以添加 -C参数
xxd查看文件编码:
xxd gbk.php
0000000: 3c3f 7068 700a 2020 7661 725f 6475 6d70 <?php. var_dump
0000010: 2862 696e 3268 6578 2822 b6ab 2229 293b (bin2hex(".."));
0000020: 0a .
1. 在 vi 或 vim 的命令状态下
:%!xxd ——将当前文本转换为16进制格式。
:%!xxd -r ——将当前文件转换回文本格式。
2. od - dump files in octal and other formats
顾名思义是查看八进制,可以通过指定参数为查看十六进制
-A 指定左边侧栏显示的地址基数,默认为八进制
-t 指定输出单元的进制格式和字节数
-x = -t x2 输出单元为双字节(注意:每单元内排列顺序从左到右为 [高字节|低字节])
Linux指令:od
示例用法:od -c hello
Linux指令:od
od命令
用户通常使用od命令查看特殊格式的文件内容。通过指定该命令的不同选项可以以十进制、八进制、十六进制和ASCII码来显示文件。
语法:od [选项] 文件…
命令中各选项的含义:
- A 指定地址基数,包括:
d 十进制
o 八进制(系统默认值)
x 十六进制
n 不打印位移值
- t 指定数据的显示格式,主要的参数有:
c ASCII字符或反斜杠序列
来自:http://blog.csdn.net/dumgeewang/article/details/7778143
http://blog.csdn.net/chenglian_999/article/details/4672177
=========================================
主要用来查看下换行符号:
#od -c S.txt
0000000 1 1 1 1 * 1 + 2 2 2 + 5 * 1 1 +
0000020 8 * 7 7 \n \n
0000026
#od -c S.txt
0000000 1 1 1 1 * 1 + 2 2 2 + 5 * 1 1 +
0000020 8 * 7 7 \n
0000025
===============Q:=========================
cat S.txt
11+2
od -c S.txt
0000000 1 1 + 2
0000004
-------------------------------------------------------------------------------
bc没有换行,cat filename |bc 会提示:
cat S.txt|bc
bc: stdin:1: syntax error: unexpected EOF
也就是说,还得有一个结尾换行符号。
两者本质区别:
如果子进程还没有结束时,父进程就结束了,那么init进程会自动接手这个子进程,进行回收。
如果父进程是循环,又没有安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束。那么子进程结束后,没有回收,就产生僵尸进程了。
前题要有如下扩展:
php -m|grep pcntl
pcntl
php -m|grep posix
posix
ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' #会发现一个僵尸进程。
Z+ 36248 36249 [php] <defunct> #主退出前此进程在,退出后只剩下下面这个进程。
Zs 38053 38055 [sh] <defunct>
如果主进程加上回收函数就不存在,如下:
返回的值可以是-1,0或者 >0的值, 如果是-1, 表示子进程出错, 如果>0表示子进程已经退出且值是退出的子进程pid,至于如何退出, 可以通过$status状态码反映:
以上来自:来自:https://www.cnblogs.com/jkko123/p/6351615.html?utm_source=itdadao&utm_medium=referral
讲讲Daemon:
脱离终端之posix_setsid,这里就是相当于下在代码就开始属于守护进程了,
主要目的脱离终端控制,自立门户。
创建一个新的会话,而且让这个pid统治这个会话,他既是会话组长,也是进程组长。
而且谁也没法控制这个会话,除了这个pid。当然关机除外。。
这时可以成做pid为这个无终端的会话组长。
注意这个函数需要当前进程不是父进程,或者说不是会话组长。
在这里当然不是,因为父进程已经被kill
来自:https://segmentfault.com/a/1190000005979154
Linux 下 popen 函数引起的僵尸进程 defunct 以及解决办法,主要是PHP主进程退出并没有等待popen的返回,没有wait导致:http://blog.csdn.net/sky_qing/article/details/22296827
概览:任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”(首先:它是wait了的,其次,子进程运行完毕,再次,父亲进程没有来得及处理(繁忙容易出现,应该还有其它也会出现..,总之父进程来不及处理。)。 以上三个状态均满足,才会有Z,否则缺一个的情况下是没有Z状态的,下面的实验没有出现繁忙,也就没有看到Z,要看到Z在Kafka的Python调用PHP,在进行压力测试时也就实实在在的看到了Z状态。)。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。
##如何避免产生僵尸进程
我们知道了僵尸进程产生的原因和危害,那么如何避免产生僵尸进程呢?
一般,为了防止产生僵尸进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。如下代码所示:
void sig_chld( int signo ) {
pid_t pid;
int stat;
pid = wait(&stat);
printf( "child %d exit\n", pid );
return;
}
int main() {
signal(SIGCHLD, &sig_chld);
}
SIGCHLD,在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。
二、开始实践研究:
1.学习一个命令行查看父子关系的Ps命令:ps -f -C
2.Python调用PHP产生僵尸进程的缘故,继承关系如下:
1号进程生下python的主进程35923,而Python产生了8个子进程(35926,35927,35928,35929,35930,35931,35932,35933),
而这8个子进程呢,又去调用了PHP可执行文件,就拿其中一个Python的了进程PID=35928,它调用PHP进程产生了多个PHP的PID(6770,6773,6774,6776,6818
),而这些因为PHP运行太快,进而导致出现了僵尸的状态,而
摘自:https://www.zhihu.com/question/26432067
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
/tmp/defunct.c
make defunct
ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 36158 34442 0 16:05 pts/12 00:00:00 ./defunct
root 36159 36158 0 16:05 pts/12 00:00:00 [defunct] <defunct>
而运行是先SSHD从1号进程继承子进程,后再 su mamingyao,再su xiangdong,一层层的继承,进而实现运行上面的进程:
上面的进程表明,只要defunc父进程不退出,且它没有wait_pid,那么它就是僵尸态,而退出后,这个僵尸态也就没有了。
结论:经实践,发现如果父进程一直运行不退出,且父进程只Fork不进行等待子进程pid = wait(&stat); 而这个僵尸的状态一直存在的,正如前面所讲,子进程运行完退出,此时如果父进程退出,这个子进程的僵尸会被1号进程清理掉,如果父进程一直不退出,则这个僵尸态一直存在,并不会被清理掉,如果调用了pid = wait(&stat); 应该在父进程不繁忙时,会立即回收,如果繁忙,可能还是会短暂出现僵尸态的情况发生,下面两段增强版本代码得到了验证:
1)父进程一直运行,不退出,僵尸一直在,退出后被1号进程清理实验:
vim /tmp/defunct/defunct.c
运行:
#./defunct
查看:
#ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 55767 55416 0 09:51 pts/11 00:00:00 ./defunct
root 55768 55767 0 09:51 pts/11 00:00:00 [defunct] <defunc
ps -efL |grep defunct
root 55767 55416 55767 0 1 09:51 pts/11 00:00:00 ./defunct
root 55768 55767 55768 0 1 09:51 pts/11 00:00:00 [defunct] <defunct>
僵尸是有的,但没有看到Z状态,呵呵,
2)父进程等待:SIGCHLD,在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。,等待子进程pid = wait(&stat);发现在父进程不繁忙时,并没有出现僵尸的情况,何为繁忙,我估计在高并发时可能也就是所谓的繁忙,在下面对Kafaka进行压力测试时的确发现有僵尸但一会又回收了,也就是说Python也调用了wait等待子进程了,但是太繁忙,Top看时其 N zombie,导致并没有立即清理 ,出现时而僵尸进程多时而被回收的情况属于正常情况。
vim /tmp/defunct/defunct.c
运行:
#./defunct
查看:
ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 57355 55416 0 10:03 pts/11 00:00:00 ./defunct
#ps -efL |grep defunct
root 58663 55416 58663 0 1 10:10 pts/11 00:00:00 ./defunct
不存在僵尸进程的标识,被wait干掉了。
附带说下孤儿进程,孤儿进程(即使父亲等待子进程signal(SIGCHLD, &sig_chld);,父亲死了,还是会成孤儿):
vim /tmp/defunct/defunct.c
./defunct
I am father process.I will sleep two seconds
pid=59405
I am child process.I am exiting.
pid=59406
子进程也一直While(1),不通出,此时看这两个进程正常:
#ps -efL |grep defunct
root 59303 55416 59303 0 1 10:15 pts/11 00:00:00 ./defunct
root 59304 59303 59304 0 1 10:15 pts/11 00:00:00 ./defunct
#ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 59303 55416 0 10:15 pts/11 00:00:00 ./defunct
root 59304 59303 0 10:15 pts/11 00:00:00 ./defunct
关键一步,杀死父PID,59405是父进程,杀死父亲(注意:如果用直接对启动进程杀死的Ctrl+c是会整个都退出,得用Kill命令才能出现孤儿进程):
kill -9 59405
出现子进程PID=59406,被1号进程收养,也就是所谓的孤儿进程:
ps -efL |grep defunct
root 59406 1 59406 0 1 10:15 pts/11 00:00:00 ./defunct
转回正题说到僵尸进程:
=========================================================================
如下:Kafaka用Python写的多进程调用PHP出现僵尸进程:
说明啥,说明如果主进程是守护进程不退出,子进程去运行PHP的清况,而不wait_pid, 会产生一堆的僵尸进程,如果有一个Python子进程死了,PHP的僵尸也就死了。或者Python有WaitPID,也就会出现僵尸态存在,一会就好了的情况,这个所谓繁忙,我估计是涉及到阻塞、网络阻塞、队列阻塞啥的引起,导致没有及时回调wait而出现了短暂的僵尸。
======================Kafka的Client用Python写的调用了PHP===============================
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -f -C php
UID PID PPID C STIME TTY TIME CMD
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -ef|grep 35928
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6774 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6776 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6778 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6779 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6784 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6789 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6790 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6793 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6796 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6798 35928 0 11:50 ? 00:00:00 [php
PID和PPID:
1、PID(process ID):
PID是程序被操作系统加载到内存成为进程后动态分配的资源。
每次程序执行的时候,操作系统都会重新加载,PID在每次加载的时候都是不同的。
2、PPID(parent process ID):PPID是程序的父进程号。
grep 35928
www 35928 35923 2 11:05 ? 00:06:47 ms-survey-kafka-client
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -f -C php
UID PID PPID C STIME TTY TIME CMD
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6774 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6776 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6818 35928 0 11:50 ? 00:00:00 [php] <defunct>
...
www 7501 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7504 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7505 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7506 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7507 35926 0 11:50 ? 00:00:00 [php] <defunct>
...
父亲进程:
www 35928 35923 2 11:05 ? 00:06:47 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:53 ms-survey-kafka-client
ps -f -C ms-survey-kafka-client
UID PID PPID C STIME TTY TIME CMD
www 35923 1 0 11:05 ? 00:00:00 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:54 ms-survey-kafka-client
www 35927 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35928 35923 2 11:05 ? 00:06:48 ms-survey-kafka-client
www 35929 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35930 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35931 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35932 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35933 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
ps -ef|grep 35923
root 31083 28863 0 15:43 pts/0 00:00:00 grep 35923
www 35923 1 0 11:05 ? 00:00:00 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:54 ms-survey-kafka-client
www 35927 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35928 35923 2 11:05 ? 00:06:48 ms-survey-kafka-client
www 35929 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35930 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35931 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35932 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35933 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
脑补:
摘自:https://michaelyou.github.io/2015/03/12/孤儿进程与僵尸进程/
##前言
孤儿继承和僵尸进程是APUE里面的一个重要概念,之前看书不仔细,也没有总结,所以这两个概念一直很模糊,只知道是父进程和子进程有一个退了,至于到底是父进程退还是子进程退会产生孤儿进程和僵尸进程,一直是我的一块心病啊。今天有空,来认真总结一下。
##基本概念
在unix/linux中,子进程是通过父进程创建的(fork)。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
我们再来分析一下:
孤儿的意思是什么?被父母抛弃了,或者没有父母。所以孤儿进程就是父进程不在了,留下子进程在继续运行。但孤儿不能自己存在啊,所以总会有好心人收养他,在unix系统里,这个好心人就是init进程,init进程会收养所有的孤儿进程,代替父进程手机子进程的终止状态。
同理,什么是僵尸?如果你死了,你就有可能成为僵尸。子进程挂了之后,有一个重要的步骤就是父进程应该调用wait或者waitpid来获取它的终止状态,让它入土为安的。但有些父母非常不负责,他没有做。所以子进程不能入土,就只能继续在系统里飘荡,成了僵尸。这不怪他们啊,都是父进程害的!
##危害
有的人就说了,那干嘛一定要父进程调用wait和waitpid来回收子进程啊,子进程挂了就让他挂好了,父进程不要回收,让系统自己把回收的事干了。我也是这样想的,可是你知道父母的通病在哪里吗?就是他们对自己的小孩,都有旺盛的控制欲!
unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是:
在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。
所以就导致了问题,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果产生大量的僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害。
孤儿进程是没有父进程的进程,处理孤儿进程的这个重任落到了init进程身上,init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。
任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。
##如何避免产生僵尸进程
我们知道了僵尸进程产生的原因和危害,那么如何避免产生僵尸进程呢?
一般,为了防止产生僵尸进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。如下代码所示:
void sig_chld( int signo ) {
pid_t pid;
int stat;
pid = wait(&stat);
printf( "child %d exit\n", pid );
return;
}
int main() {
signal(SIGCHLD, &sig_chld);
}
先在main函数中给SIGCHLD信号注册一个信号处理函数(sig_chld),然后在子进程退出的时候,内核递交一个SIGCHLD的时候就会被主进程捕获而进入信号处理函数sig_chld,然后再在sig_chld中调用wait,就可以清理退出的子进程。这样退出的子进程就不会成为僵尸进程。
但是,这种方法并不是完美的,有时候还是会有漏网之鱼,下面是就是一个例子:
我们假设有一个client/server的程序,对于每一个连接过来的client,server都启动一个新的进程去处理来自这个client的请求。然后我们有一个client进程,在这个进程内,发起了多个到server的请求(假设5个),则server会fork 5个子进程来读取client输入并处理(同时,当客户端关闭套接字的时候,每个子进程都退出);当我们终止这个client进程的时候 ,内核将自动关闭所有由这个client进程打开的套接字,那么由这个client进程发起的5个连接基本在同一时刻终止。这就引发了5个FIN,每个连接一个。server端接受到这5个FIN的时候,5个子进程基本在同一时刻终止。这就又导致差不多在同一时刻递交5个SIGCHLD信号给父进程,而最终结果大家将会发现,我们没有能够回收所有的5个进程,有僵尸进程产生了。
wait函数不能处理这种情况的原因是:所有5个信号都在信号处理函数执行之前产生,而信号处理函数只执行一次,因为Unix信号一般是不排队的。 更为严重的是,本问题是不确定的,依赖于客户FIN到达服务器主机的时机,信号处理函数执行的次数并不确定。
这种情况的正确的解决办法是调用waitpid而不是wait,方法为:信号处理函数中,在一个循环内调用waitpid,以获取所有已终止子进程的状态。我们必须指定WNOHANG选项,他告知waitpid在有尚未终止的子进程在运行时不要阻塞。(我们不能在循环内调用wait,因为没有办法防止wait在尚有未终止的子进程在运行时阻塞,wait将会阻塞到现有的子进程中第一个终止为止)。
##产生了僵尸进程怎么办
如果系统中出现了僵尸进程,如何打僵尸呢?
僵尸进程用kill命令是无法杀掉的,但是我们可以结果掉僵尸进程的爸爸,僵尸daddy挂了之后,僵尸进程就成了孤儿进程,会被init程序收养,然后init程序将其回收
如果子进程还没有结束时,父进程就结束了,那么init进程会自动接手这个子进程,进行回收。
如果父进程是循环,又没有安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束。那么子进程结束后,没有回收,就产生僵尸进程了。
前题要有如下扩展:
php -m|grep pcntl
pcntl
php -m|grep posix
posix
ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' #会发现一个僵尸进程。
Z+ 36248 36249 [php] <defunct> #主退出前此进程在,退出后只剩下下面这个进程。
Zs 38053 38055 [sh] <defunct>
如果主进程加上回收函数就不存在,如下:
返回的值可以是-1,0或者 >0的值, 如果是-1, 表示子进程出错, 如果>0表示子进程已经退出且值是退出的子进程pid,至于如何退出, 可以通过$status状态码反映:
以上来自:来自:https://www.cnblogs.com/jkko123/p/6351615.html?utm_source=itdadao&utm_medium=referral
讲讲Daemon:
脱离终端之posix_setsid,这里就是相当于下在代码就开始属于守护进程了,
主要目的脱离终端控制,自立门户。
创建一个新的会话,而且让这个pid统治这个会话,他既是会话组长,也是进程组长。
而且谁也没法控制这个会话,除了这个pid。当然关机除外。。
这时可以成做pid为这个无终端的会话组长。
注意这个函数需要当前进程不是父进程,或者说不是会话组长。
在这里当然不是,因为父进程已经被kill
来自:https://segmentfault.com/a/1190000005979154
Linux 下 popen 函数引起的僵尸进程 defunct 以及解决办法,主要是PHP主进程退出并没有等待popen的返回,没有wait导致:http://blog.csdn.net/sky_qing/article/details/22296827
概览:任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”(首先:它是wait了的,其次,子进程运行完毕,再次,父亲进程没有来得及处理(繁忙容易出现,应该还有其它也会出现..,总之父进程来不及处理。)。 以上三个状态均满足,才会有Z,否则缺一个的情况下是没有Z状态的,下面的实验没有出现繁忙,也就没有看到Z,要看到Z在Kafka的Python调用PHP,在进行压力测试时也就实实在在的看到了Z状态。)。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。
##如何避免产生僵尸进程
我们知道了僵尸进程产生的原因和危害,那么如何避免产生僵尸进程呢?
一般,为了防止产生僵尸进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。如下代码所示:
void sig_chld( int signo ) {
pid_t pid;
int stat;
pid = wait(&stat);
printf( "child %d exit\n", pid );
return;
}
int main() {
signal(SIGCHLD, &sig_chld);
}
SIGCHLD,在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。
二、开始实践研究:
1.学习一个命令行查看父子关系的Ps命令:ps -f -C
2.Python调用PHP产生僵尸进程的缘故,继承关系如下:
1号进程生下python的主进程35923,而Python产生了8个子进程(35926,35927,35928,35929,35930,35931,35932,35933),
而这8个子进程呢,又去调用了PHP可执行文件,就拿其中一个Python的了进程PID=35928,它调用PHP进程产生了多个PHP的PID(6770,6773,6774,6776,6818
),而这些因为PHP运行太快,进而导致出现了僵尸的状态,而
摘自:https://www.zhihu.com/question/26432067
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
/tmp/defunct.c
make defunct
ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 36158 34442 0 16:05 pts/12 00:00:00 ./defunct
root 36159 36158 0 16:05 pts/12 00:00:00 [defunct] <defunct>
而运行是先SSHD从1号进程继承子进程,后再 su mamingyao,再su xiangdong,一层层的继承,进而实现运行上面的进程:
上面的进程表明,只要defunc父进程不退出,且它没有wait_pid,那么它就是僵尸态,而退出后,这个僵尸态也就没有了。
结论:经实践,发现如果父进程一直运行不退出,且父进程只Fork不进行等待子进程pid = wait(&stat); 而这个僵尸的状态一直存在的,正如前面所讲,子进程运行完退出,此时如果父进程退出,这个子进程的僵尸会被1号进程清理掉,如果父进程一直不退出,则这个僵尸态一直存在,并不会被清理掉,如果调用了pid = wait(&stat); 应该在父进程不繁忙时,会立即回收,如果繁忙,可能还是会短暂出现僵尸态的情况发生,下面两段增强版本代码得到了验证:
1)父进程一直运行,不退出,僵尸一直在,退出后被1号进程清理实验:
vim /tmp/defunct/defunct.c
运行:
#./defunct
查看:
#ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 55767 55416 0 09:51 pts/11 00:00:00 ./defunct
root 55768 55767 0 09:51 pts/11 00:00:00 [defunct] <defunc
ps -efL |grep defunct
root 55767 55416 55767 0 1 09:51 pts/11 00:00:00 ./defunct
root 55768 55767 55768 0 1 09:51 pts/11 00:00:00 [defunct] <defunct>
僵尸是有的,但没有看到Z状态,呵呵,
2)父进程等待:SIGCHLD,在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。,等待子进程pid = wait(&stat);发现在父进程不繁忙时,并没有出现僵尸的情况,何为繁忙,我估计在高并发时可能也就是所谓的繁忙,在下面对Kafaka进行压力测试时的确发现有僵尸但一会又回收了,也就是说Python也调用了wait等待子进程了,但是太繁忙,Top看时其 N zombie,导致并没有立即清理 ,出现时而僵尸进程多时而被回收的情况属于正常情况。
vim /tmp/defunct/defunct.c
运行:
#./defunct
查看:
ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 57355 55416 0 10:03 pts/11 00:00:00 ./defunct
#ps -efL |grep defunct
root 58663 55416 58663 0 1 10:10 pts/11 00:00:00 ./defunct
不存在僵尸进程的标识,被wait干掉了。
附带说下孤儿进程,孤儿进程(即使父亲等待子进程signal(SIGCHLD, &sig_chld);,父亲死了,还是会成孤儿):
vim /tmp/defunct/defunct.c
./defunct
I am father process.I will sleep two seconds
pid=59405
I am child process.I am exiting.
pid=59406
子进程也一直While(1),不通出,此时看这两个进程正常:
#ps -efL |grep defunct
root 59303 55416 59303 0 1 10:15 pts/11 00:00:00 ./defunct
root 59304 59303 59304 0 1 10:15 pts/11 00:00:00 ./defunct
#ps -f -C defunct
UID PID PPID C STIME TTY TIME CMD
root 59303 55416 0 10:15 pts/11 00:00:00 ./defunct
root 59304 59303 0 10:15 pts/11 00:00:00 ./defunct
关键一步,杀死父PID,59405是父进程,杀死父亲(注意:如果用直接对启动进程杀死的Ctrl+c是会整个都退出,得用Kill命令才能出现孤儿进程):
kill -9 59405
出现子进程PID=59406,被1号进程收养,也就是所谓的孤儿进程:
ps -efL |grep defunct
root 59406 1 59406 0 1 10:15 pts/11 00:00:00 ./defunct
转回正题说到僵尸进程:
=========================================================================
如下:Kafaka用Python写的多进程调用PHP出现僵尸进程:
说明啥,说明如果主进程是守护进程不退出,子进程去运行PHP的清况,而不wait_pid, 会产生一堆的僵尸进程,如果有一个Python子进程死了,PHP的僵尸也就死了。或者Python有WaitPID,也就会出现僵尸态存在,一会就好了的情况,这个所谓繁忙,我估计是涉及到阻塞、网络阻塞、队列阻塞啥的引起,导致没有及时回调wait而出现了短暂的僵尸。
======================Kafka的Client用Python写的调用了PHP===============================
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -f -C php
UID PID PPID C STIME TTY TIME CMD
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -ef|grep 35928
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6774 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6776 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6778 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6779 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6784 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6789 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6790 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6793 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6796 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6798 35928 0 11:50 ? 00:00:00 [php
PID和PPID:
1、PID(process ID):
PID是程序被操作系统加载到内存成为进程后动态分配的资源。
每次程序执行的时候,操作系统都会重新加载,PID在每次加载的时候都是不同的。
2、PPID(parent process ID):PPID是程序的父进程号。
grep 35928
www 35928 35923 2 11:05 ? 00:06:47 ms-survey-kafka-client
[root@ilv-api_php_bj_szq_1*_70_33_140 ~]# ps -f -C php
UID PID PPID C STIME TTY TIME CMD
www 6770 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6773 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6774 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6776 35928 0 11:50 ? 00:00:00 [php] <defunct>
www 6818 35928 0 11:50 ? 00:00:00 [php] <defunct>
...
www 7501 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7504 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7505 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7506 35926 0 11:50 ? 00:00:00 [php] <defunct>
www 7507 35926 0 11:50 ? 00:00:00 [php] <defunct>
...
父亲进程:
www 35928 35923 2 11:05 ? 00:06:47 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:53 ms-survey-kafka-client
ps -f -C ms-survey-kafka-client
UID PID PPID C STIME TTY TIME CMD
www 35923 1 0 11:05 ? 00:00:00 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:54 ms-survey-kafka-client
www 35927 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35928 35923 2 11:05 ? 00:06:48 ms-survey-kafka-client
www 35929 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35930 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35931 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35932 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35933 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
ps -ef|grep 35923
root 31083 28863 0 15:43 pts/0 00:00:00 grep 35923
www 35923 1 0 11:05 ? 00:00:00 ms-survey-kafka-client
www 35926 35923 2 11:05 ? 00:06:54 ms-survey-kafka-client
www 35927 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35928 35923 2 11:05 ? 00:06:48 ms-survey-kafka-client
www 35929 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35930 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35931 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35932 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
www 35933 35923 0 11:05 ? 00:00:19 ms-survey-kafka-client
脑补:
摘自:https://michaelyou.github.io/2015/03/12/孤儿进程与僵尸进程/
##前言
孤儿继承和僵尸进程是APUE里面的一个重要概念,之前看书不仔细,也没有总结,所以这两个概念一直很模糊,只知道是父进程和子进程有一个退了,至于到底是父进程退还是子进程退会产生孤儿进程和僵尸进程,一直是我的一块心病啊。今天有空,来认真总结一下。
##基本概念
在unix/linux中,子进程是通过父进程创建的(fork)。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
我们再来分析一下:
孤儿的意思是什么?被父母抛弃了,或者没有父母。所以孤儿进程就是父进程不在了,留下子进程在继续运行。但孤儿不能自己存在啊,所以总会有好心人收养他,在unix系统里,这个好心人就是init进程,init进程会收养所有的孤儿进程,代替父进程手机子进程的终止状态。
同理,什么是僵尸?如果你死了,你就有可能成为僵尸。子进程挂了之后,有一个重要的步骤就是父进程应该调用wait或者waitpid来获取它的终止状态,让它入土为安的。但有些父母非常不负责,他没有做。所以子进程不能入土,就只能继续在系统里飘荡,成了僵尸。这不怪他们啊,都是父进程害的!
##危害
有的人就说了,那干嘛一定要父进程调用wait和waitpid来回收子进程啊,子进程挂了就让他挂好了,父进程不要回收,让系统自己把回收的事干了。我也是这样想的,可是你知道父母的通病在哪里吗?就是他们对自己的小孩,都有旺盛的控制欲!
unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是:
在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。
所以就导致了问题,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果产生大量的僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害。
孤儿进程是没有父进程的进程,处理孤儿进程的这个重任落到了init进程身上,init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。
任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。
##如何避免产生僵尸进程
我们知道了僵尸进程产生的原因和危害,那么如何避免产生僵尸进程呢?
一般,为了防止产生僵尸进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。如下代码所示:
void sig_chld( int signo ) {
pid_t pid;
int stat;
pid = wait(&stat);
printf( "child %d exit\n", pid );
return;
}
int main() {
signal(SIGCHLD, &sig_chld);
}
先在main函数中给SIGCHLD信号注册一个信号处理函数(sig_chld),然后在子进程退出的时候,内核递交一个SIGCHLD的时候就会被主进程捕获而进入信号处理函数sig_chld,然后再在sig_chld中调用wait,就可以清理退出的子进程。这样退出的子进程就不会成为僵尸进程。
但是,这种方法并不是完美的,有时候还是会有漏网之鱼,下面是就是一个例子:
我们假设有一个client/server的程序,对于每一个连接过来的client,server都启动一个新的进程去处理来自这个client的请求。然后我们有一个client进程,在这个进程内,发起了多个到server的请求(假设5个),则server会fork 5个子进程来读取client输入并处理(同时,当客户端关闭套接字的时候,每个子进程都退出);当我们终止这个client进程的时候 ,内核将自动关闭所有由这个client进程打开的套接字,那么由这个client进程发起的5个连接基本在同一时刻终止。这就引发了5个FIN,每个连接一个。server端接受到这5个FIN的时候,5个子进程基本在同一时刻终止。这就又导致差不多在同一时刻递交5个SIGCHLD信号给父进程,而最终结果大家将会发现,我们没有能够回收所有的5个进程,有僵尸进程产生了。
wait函数不能处理这种情况的原因是:所有5个信号都在信号处理函数执行之前产生,而信号处理函数只执行一次,因为Unix信号一般是不排队的。 更为严重的是,本问题是不确定的,依赖于客户FIN到达服务器主机的时机,信号处理函数执行的次数并不确定。
这种情况的正确的解决办法是调用waitpid而不是wait,方法为:信号处理函数中,在一个循环内调用waitpid,以获取所有已终止子进程的状态。我们必须指定WNOHANG选项,他告知waitpid在有尚未终止的子进程在运行时不要阻塞。(我们不能在循环内调用wait,因为没有办法防止wait在尚有未终止的子进程在运行时阻塞,wait将会阻塞到现有的子进程中第一个终止为止)。
##产生了僵尸进程怎么办
如果系统中出现了僵尸进程,如何打僵尸呢?
僵尸进程用kill命令是无法杀掉的,但是我们可以结果掉僵尸进程的爸爸,僵尸daddy挂了之后,僵尸进程就成了孤儿进程,会被init程序收养,然后init程序将其回收
如何在使用 scp 命令时递归地排除文件
Php/Js/Shell/Go jackxiang 2018-2-3 07:49
哈喽,大家好,今天小编给大家带来一篇如何在使用scp命令式递归的排除文件,希望对大家有所帮助,raksmart服务器。
首先我需要将所有包含 *.c 文件的文件夹从名为 hostA 的本地笔记本复制到 hostB。我使用的是下面的 scp 命令,但不知道如何排除特定的文件(如 *.out):
$ scp-r ~/projects/ user@hostB:/home/delta/projects/
如何告诉 scp 命令在 Linux/Unix 命令行中排除特定的文件或目录?
人们可以使用 scp 命令在网络主机之间安全地复制文件。它使用 ssh 进行数据传输和身份验证。典型的语法是:
scp file1 user@host:/path/to/dest/
scp-r /path/to/source/ user@host:/path/to/dest/
scp 排除文件
我不认为你可以在使用 scp 命令时过滤或排除文件。但是,有一个很好的解决方法来排除文件并使用 ssh 安全地复制它。本页面说明如何在使用 scp 递归复制目录时过滤或排除文件。
如何使用 rsync 命令排除文件
语法是:
rsync av -e ssh--exclude='*.out'/path/to/source/ user@hostB:/path/to/dest/
这里:
-a :递归到目录,即复制所有文件和子目录。另外,打开归档模式和所有其他选项(相当于 -rlptgoD)
-v :详细输出
-e ssh :使用 ssh 作为远程 shell,这样所有的东西都被加密
--exclude='*.out' :排除匹配模式的文件,例如 *.out 或 *.c 等。
rsync 命令的例子
在这个例子中,从 ~/virt/ 目录递归地复制所有文件,但排除所有 *.new 文件:
$ rsync -av -e ssh--exclude='*.new'~/virt/ root@CentOS7:/tmp
示例输出:
Scp exclude files but using rsync exclude command
如果远程服务器上找不到 rsync,那么 rsync 命令将失败。在这种情况下,请尝试使用以下 scp 命令,该命令在当前目录中使用 bash shell 模式匹配 (它不能与 -r 选项一起使用):
$ ls
示例输出:
centos71.log centos71.qcow2 centos71.qcow2.new centos71.v2.qcow2.new meta-data user-data
复制除 .new 之外的当前目录中的所有内容:
$ shopt -s extglob
$ scp!(*.new) root@centos7:/tmp/
示例输出:
centos71.log 100%42621.3MB/s 00:00
centos71.qcow2 100%836MB32.7MB/s 00:25
meta-data 100%4718.5KB/s 00:00
user-data 100%1543569.7KB/s 00:00
有关更多信息,请参阅以下手册页:
$ man rsync
$ manbash
$ manscp
好了今天就到这里啦,大家明天见啦。
首先我需要将所有包含 *.c 文件的文件夹从名为 hostA 的本地笔记本复制到 hostB。我使用的是下面的 scp 命令,但不知道如何排除特定的文件(如 *.out):
$ scp-r ~/projects/ user@hostB:/home/delta/projects/
如何告诉 scp 命令在 Linux/Unix 命令行中排除特定的文件或目录?
人们可以使用 scp 命令在网络主机之间安全地复制文件。它使用 ssh 进行数据传输和身份验证。典型的语法是:
scp file1 user@host:/path/to/dest/
scp-r /path/to/source/ user@host:/path/to/dest/
scp 排除文件
我不认为你可以在使用 scp 命令时过滤或排除文件。但是,有一个很好的解决方法来排除文件并使用 ssh 安全地复制它。本页面说明如何在使用 scp 递归复制目录时过滤或排除文件。
如何使用 rsync 命令排除文件
语法是:
rsync av -e ssh--exclude='*.out'/path/to/source/ user@hostB:/path/to/dest/
这里:
-a :递归到目录,即复制所有文件和子目录。另外,打开归档模式和所有其他选项(相当于 -rlptgoD)
-v :详细输出
-e ssh :使用 ssh 作为远程 shell,这样所有的东西都被加密
--exclude='*.out' :排除匹配模式的文件,例如 *.out 或 *.c 等。
rsync 命令的例子
在这个例子中,从 ~/virt/ 目录递归地复制所有文件,但排除所有 *.new 文件:
$ rsync -av -e ssh--exclude='*.new'~/virt/ root@CentOS7:/tmp
示例输出:
Scp exclude files but using rsync exclude command
如果远程服务器上找不到 rsync,那么 rsync 命令将失败。在这种情况下,请尝试使用以下 scp 命令,该命令在当前目录中使用 bash shell 模式匹配 (它不能与 -r 选项一起使用):
$ ls
示例输出:
centos71.log centos71.qcow2 centos71.qcow2.new centos71.v2.qcow2.new meta-data user-data
复制除 .new 之外的当前目录中的所有内容:
$ shopt -s extglob
$ scp!(*.new) root@centos7:/tmp/
示例输出:
centos71.log 100%42621.3MB/s 00:00
centos71.qcow2 100%836MB32.7MB/s 00:25
meta-data 100%4718.5KB/s 00:00
user-data 100%1543569.7KB/s 00:00
有关更多信息,请参阅以下手册页:
$ man rsync
$ manbash
$ manscp
好了今天就到这里啦,大家明天见啦。
[实践OK]Linux下用vi/VIM利用正则将空格替换为换行,将逗号替换为真实换行。
Unix/LinuxC技术 jackxiang 2018-2-1 11:07
背景:想到逗号替换为真正的换行,用这个\n不好使,怎么办?一查换行是\r,于是:
学习摘自:VIM如何将空格替换为换行,比如有时需要把很长的一行按空格分为多行,这时就可以用如下命令实现:
:%s/ +/\r/gc
参数解释:
%s :在整个文件范围查找替换
/ : 分隔符
+ :匹配空格,其中“ ”表示空格,+表示重复1次或多次,加在一起表示一个或多个空格。
\r :换行符
g :全局替换
c :替换前确认
来自:http://www.blogdaren.com/m/?post=128
学习摘自:VIM如何将空格替换为换行,比如有时需要把很长的一行按空格分为多行,这时就可以用如下命令实现:
:%s/ +/\r/gc
参数解释:
%s :在整个文件范围查找替换
/ : 分隔符
+ :匹配空格,其中“ ”表示空格,+表示重复1次或多次,加在一起表示一个或多个空格。
\r :换行符
g :全局替换
c :替换前确认
来自:http://www.blogdaren.com/m/?post=128
背景:有时想要打开相同页面,快速写或粘贴一篇博文到自己博客网站上,每次抄作都需要新开一个Tab,再粘贴博客网站地址,再粘贴进入新开的Tab里,效率不高,怎么办,有没有插件,我一找,还真有这样的一个插件。
插件:CLEAN crxMouse Gestures
插件地址:https://chrome.google.com/webstore/detail/clean-crxmouse-gestures/mjidkpedjlfnanainpdfnedkdlacidla?hl=zh-CN
插件介绍:
干净版! 原名:Gestures for Chrome(TM)汉化版.方便,快捷,充分发掘鼠标的所有操作.功能包括:鼠标手势,超级拖曳,滚轮手势,摇杆手势,平滑滚动,标签页列表等.
本版本是基于crxMouse Gestures优化的版本,整理优化代码并去除了该版本中在后台上传用户浏览过的网页等隐私数据的代码。
方便,快捷,充分发掘鼠标的所有操作.功能包括:鼠标手势,超级拖曳,滚轮手势,摇杆手势,平滑滚动,标签页列表,后台打开标签页等。
---------
默认手势和自定义鼠标手势地址,在浏览器地址栏里输入:chrome-extension://mjidkpedjlfnanainpdfnedkdlacidla/options.html ,左侧点鼠标手势。
标签最常用,特自研三个常用标签部分:
零)进入手势扩展设置:
右上左上默认是进入扩展。
一)自定义手势:
1)复制当前标签:
设置、鼠标手势、添加新手势、顺时针画个圈,选择下拉里面的动作:复制当前标签。 (左下右)
2)新建标签页:
设置、鼠标手势、添加新手势、向上、向左、向右:新建标签页。 (上左右)。
3)关闭标签页:
设置、鼠标手势、添加新手势、向下、向左、向右:关闭标签页。 (下左右)。
二)系统默认常用标签手势:
切换至左侧标签页:上左
切换至右侧标签页:上右
三)键盘实现URL历史后退:
Alt+键盘左键头
四)前进后退:
后退:左
前进:右
五)刷新/强刷/上拉/下拉:
刷新:上下
强刷:上下上
上拉:下
下拉:上
六)查看网页源代码:
下左 或者 左下
七)强制刷新网页:
上、右、下、左、上,也就是顺时针画个圈。(右、下、左、上默认是进入扩展!)
八)打开粘贴板上的网址:
下、左、上、右、下,前提是里面真是一个网址,否则不会打开新的标签链接的。
多台相同手势配置文件导入导出,方法,来源:http://jackxiang.com/post/6619/
来个手势的,配置自定义手势太麻烦,直接打包, 发现并没有把之前的手势设置进去,但这个插件提供了一个导出和倒入功能,可把之前的设置导入,相当有用,不用再次设置了,DownLoasd:,在Google点插件,再点选择->高级选项->导出时->Txt框里有数据->拷贝出来成txt,上传到另一台计算机上->粘贴进去->导入即可。
Mac和Linux下注意设置下右键900ms双击以实现在Chrome下的右键:
Linux/Mac选项 [V]消除Linux/Mac右键菜单对本扩展的影响(双击弹出右键菜单).
双击间隔最长时间(ms):900 ms
该选项修复非Windows平台上,右键菜单影响某些功能的正常使用,强烈建议Linux/Mac用户勾选此项.
Google Chrome右键不灵,Chrome for Mac为何双击右键才出现菜单?http://ju.outofmemory.cn/entry/315312
插件:CLEAN crxMouse Gestures
插件地址:https://chrome.google.com/webstore/detail/clean-crxmouse-gestures/mjidkpedjlfnanainpdfnedkdlacidla?hl=zh-CN
插件介绍:
干净版! 原名:Gestures for Chrome(TM)汉化版.方便,快捷,充分发掘鼠标的所有操作.功能包括:鼠标手势,超级拖曳,滚轮手势,摇杆手势,平滑滚动,标签页列表等.
本版本是基于crxMouse Gestures优化的版本,整理优化代码并去除了该版本中在后台上传用户浏览过的网页等隐私数据的代码。
方便,快捷,充分发掘鼠标的所有操作.功能包括:鼠标手势,超级拖曳,滚轮手势,摇杆手势,平滑滚动,标签页列表,后台打开标签页等。
---------
默认手势和自定义鼠标手势地址,在浏览器地址栏里输入:chrome-extension://mjidkpedjlfnanainpdfnedkdlacidla/options.html ,左侧点鼠标手势。
标签最常用,特自研三个常用标签部分:
零)进入手势扩展设置:
右上左上默认是进入扩展。
一)自定义手势:
1)复制当前标签:
设置、鼠标手势、添加新手势、顺时针画个圈,选择下拉里面的动作:复制当前标签。 (左下右)
2)新建标签页:
设置、鼠标手势、添加新手势、向上、向左、向右:新建标签页。 (上左右)。
3)关闭标签页:
设置、鼠标手势、添加新手势、向下、向左、向右:关闭标签页。 (下左右)。
二)系统默认常用标签手势:
切换至左侧标签页:上左
切换至右侧标签页:上右
三)键盘实现URL历史后退:
Alt+键盘左键头
四)前进后退:
后退:左
前进:右
五)刷新/强刷/上拉/下拉:
刷新:上下
强刷:上下上
上拉:下
下拉:上
六)查看网页源代码:
下左 或者 左下
七)强制刷新网页:
上、右、下、左、上,也就是顺时针画个圈。(右、下、左、上默认是进入扩展!)
八)打开粘贴板上的网址:
下、左、上、右、下,前提是里面真是一个网址,否则不会打开新的标签链接的。
多台相同手势配置文件导入导出,方法,来源:http://jackxiang.com/post/6619/
来个手势的,配置自定义手势太麻烦,直接打包, 发现并没有把之前的手势设置进去,但这个插件提供了一个导出和倒入功能,可把之前的设置导入,相当有用,不用再次设置了,DownLoasd:
下载文件
Mac和Linux下注意设置下右键900ms双击以实现在Chrome下的右键:
Linux/Mac选项 [V]消除Linux/Mac右键菜单对本扩展的影响(双击弹出右键菜单).
双击间隔最长时间(ms):900 ms
该选项修复非Windows平台上,右键菜单影响某些功能的正常使用,强烈建议Linux/Mac用户勾选此项.
Google Chrome右键不灵,Chrome for Mac为何双击右键才出现菜单?http://ju.outofmemory.cn/entry/315312
gcc编译参数指定编码格式,exbuffer.c——纯C写的TCP中的粘包、分包问题的解决方案
Unix/LinuxC技术 jackxiang 2018-1-22 23:19
https://github.com/play175/exbuffer.c/blob/master/mingw.makefile 内容:
-finput-charset 指定源文件的编码(若不指定,默认是UTF-8)
-fexec-charset 指定多字节字符串(const char*)常量在编译后的程序里保存的编码集(若不指定,默认是UTF-8)
摘自 :http://blog.csdn.net/qq_28234213/article/details/73277748
exbuffer.c——纯C写的TCP中的粘包、分包问题的解决方案里的mingw.makefile :
https://yoyo.play175.com/p/exbuffer_c.html
-finput-charset 指定源文件的编码(若不指定,默认是UTF-8)
-fexec-charset 指定多字节字符串(const char*)常量在编译后的程序里保存的编码集(若不指定,默认是UTF-8)
摘自 :http://blog.csdn.net/qq_28234213/article/details/73277748
exbuffer.c——纯C写的TCP中的粘包、分包问题的解决方案里的mingw.makefile :
https://yoyo.play175.com/p/exbuffer_c.html
结论:最新版的chrome已经更简单了,通过对着标签页点右键,就有静音选项了~
点击链接chrome://flags/#enable-tab-audio-muting开启声音管理
重启浏览器
重启完成后,点击标签页上的小喇叭就可以禁止声音
这个问题也困扰了我很久,直到我彻底忍无可忍了,终于Google了一下答案:chrome://flags/#enable-tab-audio-muting 开启功能后,点击标签页上的小喇叭即可参考文献:开启 Chrome 自带的标签页静音功能[Chrome]另外,最新版的chrome已经更简单了,通过对着标签页点右键,就有静音选项了~
作者:知乎用户
链接:https://www.zhihu.com/question/20336805/answer/33871967
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
点击链接chrome://flags/#enable-tab-audio-muting开启声音管理
重启浏览器
重启完成后,点击标签页上的小喇叭就可以禁止声音
这个问题也困扰了我很久,直到我彻底忍无可忍了,终于Google了一下答案:chrome://flags/#enable-tab-audio-muting 开启功能后,点击标签页上的小喇叭即可参考文献:开启 Chrome 自带的标签页静音功能[Chrome]另外,最新版的chrome已经更简单了,通过对着标签页点右键,就有静音选项了~
作者:知乎用户
链接:https://www.zhihu.com/question/20336805/answer/33871967
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
[浅显易懂]和TCP三次握手相关的TCP报文中的重要标志位
Unix/LinuxC技术 jackxiang 2018-1-10 20:49
看了很多tcp文章都看不懂,这篇文章好像懂了,有空试试,说的是不是真的。
和三次握手相关的TCP报文中的重要标志位
昨天的文章中,结合Wireshark抓包和大家讨论了三次握手的相关知识点,评论中有些读者对序号,确认序号,以及SYN&ACK等标志位还有一些疑问,这里简单再说一下我的理解。其中ACK的32位值在Wireshark抓包时显示的是相对的值,可设置为显示真实值:http://mini.eastday.com/a/180131063435528.html
首先,由TCP协议报文的格式可知,在报文中我们主要关注与《32位序列号》,《32位确认序号》,和SYN和ACK标志位。因为这四个要素和三次握手紧密相关。阅读全文
和三次握手相关的TCP报文中的重要标志位
昨天的文章中,结合Wireshark抓包和大家讨论了三次握手的相关知识点,评论中有些读者对序号,确认序号,以及SYN&ACK等标志位还有一些疑问,这里简单再说一下我的理解。其中ACK的32位值在Wireshark抓包时显示的是相对的值,可设置为显示真实值:http://mini.eastday.com/a/180131063435528.html
首先,由TCP协议报文的格式可知,在报文中我们主要关注与《32位序列号》,《32位确认序号》,和SYN和ACK标志位。因为这四个要素和三次握手紧密相关。阅读全文