2018年3月

一、进程状态

通常情况下,我们描述进程的状态主要有三种:

  • 就绪态:进程已经拥有了执行条件,但是没有获取到CPU,无法执行。
  • 运行态:进程已经占有了CPU,此时正在CPU上运行。
  • 阻塞态:进程在等待某项服务、信号或者外部操作等时候的状态。

三者之间的转化过程:

状态说明:

  1. 就绪 => 运行:进程被调度,获得运行时机。
  2. 运行 => 就绪:运行时间片到了,CPU让出给其他进程运行。
  3. 运行 => 阻塞:请求服务、信号、IO或是外部操作等场景。
  4. 阻塞 => 就绪:获得了输入条件,如收到信号以及读到磁盘数据等。

为什么阻塞态到就绪态和运行态之间不能相互转化

进程处于阻塞态被唤醒时,不能直接就抢占到CPU执行,而是要等待系统调度后才能继续运行,所以必须先放到就绪态中。而处于就绪态的进程,是没有运行的,状态是不会变化的,所以不能直接变成阻塞态。

在大多数的操作系统描述中,进程可能还存在新建和终止的状态,他们之间的转态变化为:

二、linux系统中的进程状态

linux系统中的进程可以分为以下几种状态:

  • 可运行态

    • 就绪态:等待被调度
    • 运行态:正在运行
  • 阻塞态

    • 浅阻塞:可中断,能被信号或时钟唤醒
    • 深阻塞:不可中断,不能被信号或时钟唤醒
  • 僵死态:进程执行中止,已经释放了大部分资源
  • 挂起态:进程被挂起,常出现在调试场景

lnmp环境中,php算是最难安装的一个了,之前各种鼓捣搞了好多次,查阅了无数资料才终于有点经验了,记录下来。

一、安装依赖项

php的依赖项相当多,大部分都是运行环境需要的库环境。有的直接yum 就能安装,有的就需要手动编译安装了。反正一个原则:能用yum安装的尽量用yum。

yum install gcc bison bison-devel zlib-devel libmcrypt-devel mcrypt mhash-devel \
    openssl-devel libxml2-devel libcurl-devel bzip2-devel readline-devel libedit-devel \
    sqlite-devel jemalloc jemalloc-devel -y
    
yum install libpng-devel libjpeg-devel libxslt libxslt-devel \
    libmcrypt-devel mhash mcrypt -y

- 阅读剩余部分 -

之前在wordpress上有写过一篇安装的步骤:源码编译安装nginx

但是今天找到了一个更简单的方法,简单几步就能装好:

  • 解决依赖关系和添加用户
# 安装依赖项
## centos
yum install prce pcre-devel openssl openssl-devel -y
## ubuntu
apt-get install openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev
 
# 添加用户
useradd www -s /sbin/nologin -M
  • 下载安装
wget http://mirrors.163.com/nginx/debian/pool/nginx/n/nginx/nginx_1.12.2.orig.tar.gz
tar -zxvf nginx_1.12.2.orig.tar.gz
cd nginx-1.12.2
./configure --user=www --group=www --prefix=/usr/local/nginx-1.12.2 --with-http_stub_status_module --with-http_ssl_module
make && make install
ln -s /usr/local/nginx-1.12.2/ /usr/local/nginx
  • 添加配置文件和服务

添加配置文件目录:

mkdir /etc/nginx
cp /usr/local/nginx/conf/* /etc/nginx

然后复制以下内容到/etc/init.d/nginx

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  NGINX is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/etc/nginx/nginx.conf"

[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

make_dirs() {
   # make required directories
   user=`$nginx -V 2>&1 | grep "configure arguments:.*--user=" | sed ''s/[^*]*--user=\([^ ]*\).*/\1/g'' -`
   if [ -n "$user" ]; then
      if [ -z "`grep $user /etc/passwd`" ]; then
         useradd -M -s /bin/nologin $user
      fi
      options=`$nginx -V 2>&1 | grep ''configure arguments:''`
      for opt in $options; do
          if [ `echo $opt | grep ''.*-temp-path''` ]; then
              value=`echo $opt | cut -d "=" -f 2`
              if [ ! -d "$value" ]; then
                  # echo "creating" $value
                  mkdir -p $value && chown -R $user $value
              fi
          fi
       done
    fi
}

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    sleep 1
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac
  • 启动服务
service nginx start

sudo: **: command not found的解决方法

使用sudo 命令以root 身份运行命令vi 时报错:

sudo: vi: command not found

百度一番发现使用sudo 执行命令时,它只会去找系统内置已经拥有的命令,也就是说系统智慧在默认的PATH 目录下去寻找,另外添加的PAHT 不会去查找。同时,对于命令别名系统也不会去执行。

因为下午重装了vi ,直接把bin 目录包含在PATH 中,root用户可以运行,但是sudo 无法运行。解决的方法就是在/usr/bin/ 目录下给vi 命令创建软链接:

ln -s /usr/local/vim/bin/vim /usr/bin/vi
ln -s /usr/local/vim/bin/vim /usr/bin/vim

|
| -(n) | 仅显示最近的 n 条提交 |
| --since, --after | 仅显示指定时间之后的提交。 |
| --until, --before | 仅显示指定时间之前的提交。 |
| --author | 仅显示指定作者相关的提交。 |
| --committer | 仅显示指定提交者相关的提交。 |

$ git log --after=2.weeks --pretty=oneline
37db3c6686ff9382eb1ba6adaa4bae9a77459b69 (HEAD -> master) update
36c2d3c6285618f99706ae962c5a41be47253c54 first commit
$ git log --author="马谦马谦马谦" --pretty=oneline
37db3c6686ff9382eb1ba6adaa4bae9a77459b69 (HEAD -> master) update
36c2d3c6285618f99706ae962c5a41be47253c54 first commit

模板是C++中一个重要的部分,也是泛型编程的基础,一个模板就是一个创建类或函数的蓝图,使用它在很多时候都能给我们带来巨大的便利。

一、函数模板

定义一个函数模板的语法为:

template <typename T>
int compare(const T &v1, const T &v2)
{
    if (v1 < v2) return -1;
    else if (v1 > v2) return 1;
    else return 0;
}

模板以关键字template 开始,后面跟一个模板参数列表,和函数的形参一样,参数列表可以是多个以逗号隔开的一个或多个参数,外部用<> 包起来。

T 代表一种数据类型,可以为任意的内置类型或自定义类,只要该类型实现了函数重载,就可以通过compare() 函数进行比较。

- 阅读剩余部分 -

问题描述

使用git pull 或者git push 时出现以下错误信息:

fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

问题原因及解决方案

上传或者下拉的文件太大了,导致传输失败,在配置文件中修改缓存大小即可。

git config --global http.postBuffer 524288000

0x01 介绍

C++类中有两种方式可以用来初始化成员变量,一种最常见的是在构造函数内部直接对成员函数赋值:

class CTest{
    int m_a, m_b;
    CTest(int a, int b){
        m_a = a;
        m_b = b;
    }
}

另外一种方式就是通过构造函数的初始值列表来完成初始化:

class CTest{
    int m_a, m_b;
    CTest(int a, int b) : m_a(a), m_b(b){}
}

这种在构造函数后加一个冒号然后初始化的方式叫做构造函数初始值列表,它更优于第一种初始化方式。

0x02 初始值列表的必要性

在以下情况下,必需使用初始值列表方式来初始化:

  • 类成员包含const对象时。
  • 在类A没有提供默认构造函数且被类B包含或者继承时,类B必需使用默认初始化方式初始化A。

对于第一个条件比较好理解,因为const本身在初始化后是无法再赋值的,所以必须使用初始化列表来对其初始化。

对于第二种情况,因为根据构造函数的执行顺序,在构造类B时必须先构造类A的构造函数,但类A并没有提供默认的构造函数,此时导致编译器找不到合适的构造函数,所以对象构造失败。因此这里必须在初始值列表中初始化。

#pragma once
#include <iostream>
class CAnimal
{
public:
    CAnimal(int weight) :m_weight(weight) {
    }
    int m_weight;
};

class CDog {
public:
    CAnimal m_a;
    const int m_b;
    CDog(int a, int b) : m_b(b), m_a(a){
    }
};

0x02 初始值列表的效率

使用普通方式初始化时编译器会先执行一次对象的默认构造函数,然后才会对其赋值,初始化时执行了两个步骤。

#include <iostream>
class CAnimal
{
public:
    CAnimal() { std::cout << "default" << std::endl; }  // 添加默认初始化函数
    CAnimal(int weight) :m_weight(weight) {
    }
    int m_weight;
};

class CDog : public CAnimal {
public:
    CDog(int weight) {
        m_weight = weight;
    }
    // 初始值列表,和上面的构造函数不可共存
    CDog(int weight): CAnimal(weight) {
    }
};

执行CDog构造函数时会先执行CAnimal的默认构造函数,输出defualt 然后后才会执行m_weight = weight。但是对于初始值列表方式来说并不会执行两步,直接通过相应的构造函数初始化就完成了,相对来说简化了一个过程,效率肯定也会高一些。

0x03 初始化顺序

使用初始值列表初始化时,初始化的顺序是根据成员变量定义的顺序来的,并不是初始值列表的顺序。

class CAnimal
{
public:
    CAnimal(int weight) :m_weight(weight) {
        std::cout << weight << std::endl;
    }
    int m_weight;
};

class CDog {
public:
    CAnimal m_a, m_b;
    CDog(int a, int b) : m_b(b), m_a(a){
    }
};

实例一个对象CDog d(1, 2) ,结果会输出:

1
2

并不是根据初始值列表先用2初始化m_b,可见初始顺序是根据定义顺序来的。