├── ipc ├── fcntl │ ├── seqno │ ├── lock_main.c │ ├── lock_define.c │ ├── lock_define.h │ └── README.md ├── pipe │ ├── data.txt │ ├── get_sys_conf.c │ ├── pipe02.c │ ├── pipe01.c │ ├── fifo_read.c │ ├── fifo_write.c │ └── README.md ├── mutex_cond │ ├── makefile │ ├── prodcons_mutex.c │ ├── prodcons_mutex_cond.c │ └── README.md ├── unpipc.h ├── posix_semaphore │ ├── producer_consumer │ │ ├── makefile │ │ ├── producer_consumer02.c │ │ └── producer_consumer01.c │ ├── semunlink.c │ ├── get_sys_conf.c │ ├── semgetvalue.c │ ├── sempost.c │ ├── makefile │ ├── semwait.c │ ├── semcreate.c │ └── README.md ├── mmap │ ├── shmunlink.c │ ├── pro_con.h │ ├── shmwrite.c │ ├── shmread.c │ ├── shmcreate.c │ ├── count03_client.c │ ├── count03_server.c │ ├── makefile │ ├── count01.c │ ├── count02.c │ ├── producer.c │ ├── consumer.c │ └── README.md ├── posix_msg_queue │ ├── mq_unlink.c │ ├── get_sys_conf.c │ ├── mq_send.c │ ├── makefile │ ├── mq_recv.c │ ├── mq_create.c │ ├── mq_notify04.c │ ├── mq_notify03.c │ ├── mq_notify01.c │ ├── mq_notify02.c │ └── signal_realtime.c └── rd_wr_lock │ └── README.md ├── cmake ├── t4 │ ├── CMakeLists.txt │ └── src │ │ ├── main.cpp │ │ └── CMakeLists.txt ├── t3 │ ├── lib_hello │ │ ├── hello.h │ │ ├── hello.cpp │ │ └── CMakeLists.txt │ └── CMakeLists.txt ├── t6 │ ├── src │ │ ├── main.cpp │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── cmake │ │ └── FindHELLO.cmake ├── t2 │ ├── src │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── CMakeLists.txt ├── t5 │ ├── CMakeLists.txt │ └── src │ │ ├── CMakeLists.txt │ │ └── main.c └── t1 │ ├── main.cpp │ └── CMakeLists.txt ├── boost ├── makefile ├── my_first_boost.cpp └── demo_regex.cpp ├── README.md ├── py ├── log_basic │ ├── mylib.py │ ├── log_simple.py │ ├── log_to_file.py │ ├── logging_from_multi_modules.py │ └── logging_format.py ├── log_advanced │ ├── logging.conf │ ├── logging_config_in_code.py │ ├── logging_rotate_by_size.py │ ├── logging_rotate_by_time.py │ ├── logging_rotate_on_restart.py │ ├── README.md │ ├── logging_config_with_file.py │ └── logging_config_with_dictfile.py └── demo_time.py ├── utility ├── example_getcwd.c ├── shmdata.h ├── getenv_test.c ├── signal01.c ├── signal03.c ├── zombie_test.c ├── signal02.c ├── strtok_example.c ├── print_backtrace.c ├── byteorder.c ├── atexit_test.c ├── chdir_test.c ├── getopt_test.c ├── signal04.c ├── jump_test.c ├── msg_recv.c ├── back_trace01.c ├── msg_send.c ├── shmread.c ├── shmwrite.c ├── url_decode.c ├── seml01.c └── parse_lc_rules.c ├── thrift └── 01 │ ├── student.thrift │ ├── gen-cpp │ ├── makefile │ ├── student_constants.cpp │ ├── student_constants.h │ ├── student_types.h │ ├── Serv_server.skeleton.cpp │ ├── student_types.cpp │ └── Serv.h │ ├── makefile │ ├── README.md │ └── client.cpp ├── pthread ├── README.md ├── pthread_hello.c ├── pthread_arg_error.c ├── pthread_dotprod_serial.c ├── pthread_arg1.c ├── pthread_stack.c ├── pthread_join.c ├── pthread_arg2.c ├── pthread_dotprod_mutex.c └── pthread_condvar.c ├── protobuf ├── addressbook.proto ├── reader.cpp └── write.cpp ├── testcode ├── inherited_virtual_func.c ├── check_os.cpp └── class_bytes_align.cpp ├── network ├── sockclient2.c ├── sockclient.c ├── sockserver.c ├── sockserver2.c ├── strcliselect.c └── strservselect.c └── openssl_demo ├── README.md ├── openssl_sign_verify.cpp ├── aes_demo.cpp ├── openssl_rsa_demo2.cpp ├── openssl_rsa_demo3.cpp └── openssl_rsa_demo1.cpp /ipc/fcntl/seqno: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /ipc/pipe/data.txt: -------------------------------------------------------------------------------- 1 | this is a test file 2 | it is used to test fifo read and write 3 | goodbye 4 | -------------------------------------------------------------------------------- /cmake/t4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(T4) 3 | ADD_SUBDIRECTORY(src) 4 | -------------------------------------------------------------------------------- /cmake/t3/lib_hello/hello.h: -------------------------------------------------------------------------------- 1 | #ifndef HELLO_H 2 | #define HELLO_H 3 | 4 | void Hello(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /cmake/t6/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | Hello(); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /boost/makefile: -------------------------------------------------------------------------------- 1 | demo_regex: 2 | g++ demo_regex.cpp -o demo_regex -lboost_regex 3 | 4 | clean: 5 | rm demo_regex -f 6 | -------------------------------------------------------------------------------- /cmake/t4/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | Hello(); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Demo 2 | ==== 3 | 4 | It is the basic skill that is the most important. 5 | 6 | Here are some little demos, that I write for reference. 7 | -------------------------------------------------------------------------------- /cmake/t2/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 2 | ADD_EXECUTABLE(t2 ${SRC_LIST}) 3 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 4 | -------------------------------------------------------------------------------- /py/log_basic/mylib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import logging 5 | 6 | def do_something(): 7 | logging.info("Doing something") 8 | -------------------------------------------------------------------------------- /cmake/t5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(t5) 3 | MESSAGE(STATUS "此Project演示了如何使用cmake预定义的cmake模块(FindCURL.cmake)") 4 | ADD_SUBDIRECTORY(src) 5 | -------------------------------------------------------------------------------- /py/log_basic/log_simple.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import logging 5 | 6 | logging.warning("watch out!") 7 | logging.info("i told you so") 8 | 9 | -------------------------------------------------------------------------------- /cmake/t3/lib_hello/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hello.h" 3 | 4 | using namespace std; 5 | 6 | void Hello(void) 7 | { 8 | cout << "hello world" << endl; 9 | } 10 | -------------------------------------------------------------------------------- /cmake/t1/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(int argc, char **argv) 6 | { 7 | cout << "hello world" << endl; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /cmake/t2/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(int argc, char **argv) 6 | { 7 | cout << "hello world" << endl; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /cmake/t3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(T3) 3 | # 若变量BUILD_SHARED_LIBS没有设置,并且在ADD_LIBRARY时没有指定库类型 4 | # 默认生成的都是静态库 5 | #SET(BUILD_SHARED_LIBS on) 6 | ADD_SUBDIRECTORY(lib_hello) 7 | 8 | -------------------------------------------------------------------------------- /utility/example_getcwd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define CWD getcwd(NULL, 0) 5 | int main() 6 | { 7 | printf("%s%c%s\n", CWD, '/', "hello"); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /thrift/01/student.thrift: -------------------------------------------------------------------------------- 1 | struct Student 2 | { 3 | 1: i32 sno, 4 | 2: string sname, 5 | 3: bool ssex, 6 | 4: i16 sage, 7 | } 8 | 9 | service Serv 10 | { 11 | void put(1: Student s), 12 | } 13 | -------------------------------------------------------------------------------- /cmake/t2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(T2) 3 | 4 | MESSAGE(STATUS "This is the binary dir: " ${PROJECT_BINARY_DIR}) 5 | MESSAGE(STATUS "This is the source dir: " ${PROJECT_SOURCE_DIR}) 6 | ADD_SUBDIRECTORY(src) 7 | -------------------------------------------------------------------------------- /cmake/t6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(HELLO) 3 | MESSAGE(STATUS "此Project演示了如何使用自定义的cmake模块(FindHELLO.cmake)") 4 | 5 | SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 6 | ADD_SUBDIRECTORY(src) 7 | 8 | 9 | -------------------------------------------------------------------------------- /utility/shmdata.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHMDATA_H 2 | #define _SHMDATA_H 3 | 4 | #define TEXT_SZ 2048 5 | 6 | struct shared_use_st 7 | { 8 | int written; //作为一个标志,非0表示可读,0表示可写 9 | char text[TEXT_SZ]; //记录写入和读取的文本 10 | }; 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /cmake/t1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(T1) 2 | SET(SRC_LIST main.cpp) 3 | 4 | MESSAGE(STATUS "This is the binary dir: " ${PROJECT_BINARY_DIR}) 5 | MESSAGE(STATUS "This is the source dir: " ${PROJECT_SOURCE_DIR}) 6 | 7 | # 此处的t1跟PROJECT定义的T1没什么关系 8 | ADD_EXECUTABLE(t1 ${SRC_LIST}) 9 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/makefile: -------------------------------------------------------------------------------- 1 | simple_server: 2 | g++ -g -I /usr/local/include/thrift/ *.cpp -o server -lthrift -DSIMPLE_SERVER 3 | 4 | nonblock_server: 5 | g++ -g -I /usr/local/include/thrift/ *.cpp -o server -lthriftnb -levent -lthrift -DNONBLOCK_SERVER 6 | 7 | clean: 8 | rm server -f 9 | -------------------------------------------------------------------------------- /py/log_basic/log_to_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import logging 5 | 6 | logging.basicConfig(filename='example.log', level=logging.DEBUG) 7 | logging.debug("This msg should go to the log file") 8 | logging.info("So should this") 9 | logging.warning("And this, too") 10 | -------------------------------------------------------------------------------- /boost/my_first_boost.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | using namespace boost::lambda; 9 | typedef std::istream_iterator in; 10 | 11 | std::for_each( 12 | in(std::cin), in(), std::cout << (_1 * 3) << " "); 13 | } 14 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/student_constants.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.1) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "student_constants.h" 8 | 9 | 10 | 11 | const studentConstants g_student_constants; 12 | 13 | studentConstants::studentConstants() { 14 | } 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ipc/mutex_cond/makefile: -------------------------------------------------------------------------------- 1 | FLAGS = -Wall -g 2 | 3 | all: prodcons_mutex prodcons_mutex_cond 4 | 5 | prodcons_mutex: prodcons_mutex.c 6 | gcc $(FLAGS) prodcons_mutex.c -o prodcons_mutex -pthread 7 | 8 | prodcons_mutex_cond: prodcons_mutex_cond.c 9 | gcc $(FLAGS) prodcons_mutex_cond.c -o prodcons_mutex_cond -pthread 10 | 11 | clean: 12 | rm -f prodcons_mutex prodcons_mutex_cond 13 | -------------------------------------------------------------------------------- /ipc/unpipc.h: -------------------------------------------------------------------------------- 1 | #ifndef UNPIPC_H 2 | #define UNPIPC_H 3 | 4 | #include 5 | 6 | #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // default permissions for new files 7 | 8 | #define FIFO "/tmp/my_fifo" 9 | 10 | 11 | #define MIN(a, b) (a)>(b)?(b):(a) 12 | #define MAXNITEMS 1000000 13 | #define MAXNTHREADS 100 14 | 15 | #define MAXLINE 80 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /py/log_basic/logging_from_multi_modules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import logging 5 | import mylib 6 | 7 | def main(): 8 | logging.basicConfig(filename="myapp.log", level=logging.INFO) 9 | logging.info("started") 10 | mylib.do_something() 11 | logging.info("Finished") 12 | 13 | if __name__ == "__main__": 14 | main() 15 | 16 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/producer_consumer/makefile: -------------------------------------------------------------------------------- 1 | all:producer_consumer01 producer_consumer02 2 | 3 | producer_consumer01: producer_consumer01.c 4 | gcc producer_consumer01.c -o producer_consumer01 -pthread 5 | 6 | producer_consumer02: producer_consumer02.c 7 | gcc producer_consumer02.c -o producer_consumer02 -pthread 8 | 9 | clean: 10 | rm -f producer_consumer01 11 | rm -f producer_consumer02 12 | 13 | -------------------------------------------------------------------------------- /thrift/01/makefile: -------------------------------------------------------------------------------- 1 | simple_client: 2 | g++ -g -I/usr/local/include/thrift -I gen-cpp/ gen-cpp/Serv.cpp gen-cpp/student_types.cpp gen-cpp/student_constants.cpp client.cpp -o client -lthrift -DSIMPLE_SERVER 3 | 4 | nonblock_client: 5 | g++ -g -I/usr/local/include/thrift -I gen-cpp/ gen-cpp/Serv.cpp gen-cpp/student_types.cpp gen-cpp/student_constants.cpp client.cpp -o client -lthrift -DNONBLOCK_SERVER 6 | 7 | clean: 8 | rm client -f 9 | -------------------------------------------------------------------------------- /utility/getenv_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | char *value = NULL; 7 | 8 | if (argc != 2) 9 | { 10 | printf("pls usage like program argv\n"); 11 | return 0; 12 | } 13 | value = getenv(argv[1]); 14 | if (value != NULL) 15 | { 16 | printf("getenv:%s = %s\n", argv[1], value); 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /utility/signal01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void sig_handler(int sig) 6 | { 7 | printf("\nouch, got a signal:%d\n", sig); 8 | signal(sig, SIG_DFL);//不恢复的话,ctrl + c就停不了程序了 9 | } 10 | 11 | 12 | int main() 13 | { 14 | signal(SIGINT, sig_handler); 15 | while (1) 16 | { 17 | printf("hello world\n"); 18 | sleep(1); 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /cmake/t4/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 2 | LINK_DIRECTORIES(/home/carl/cmake/t3/build/lib) # 这行一定要在ADD_EXECUTABLE前面 3 | ADD_EXECUTABLE(t4 ${SRC_LIST}) 4 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 5 | 6 | SET(CMAKE_PROJECT_DIR /home/carl/cmake) # cmake文件夹的位置 7 | INCLUDE_DIRECTORIES(${CMAKE_PROJECT_DIR}/t3/lib_hello) 8 | TARGET_LINK_LIBRARIES(t4 hello) # 链接动态库 9 | #TARGET_LINK_LIBRARIES(t4 libhello.a) # 链接静态库 10 | -------------------------------------------------------------------------------- /ipc/pipe/get_sys_conf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(int argc, char **argv) 7 | { 8 | if (2 != argc) 9 | { 10 | fprintf(stderr, "pls usage %s \n", argv[0]); 11 | exit(EXIT_FAILURE); 12 | } 13 | 14 | printf("PIPE_BUF = %ld, OPEN_MAX = %ld\n", 15 | pathconf(argv[1], _PC_PIPE_BUF), sysconf(_SC_OPEN_MAX)); 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /utility/signal03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int alarm_fired = 0; 6 | 7 | void sig_handler(int sig) 8 | { 9 | printf("\nouch, got a signal:%d\n", sig); 10 | alarm_fired = 1; 11 | } 12 | 13 | 14 | int main() 15 | { 16 | signal(SIGALRM, sig_handler); 17 | alarm(5); 18 | pause(); 19 | 20 | if (alarm_fired == 1) 21 | printf("\ngot a signal\n"); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/student_constants.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.1) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef student_CONSTANTS_H 8 | #define student_CONSTANTS_H 9 | 10 | #include "student_types.h" 11 | 12 | 13 | 14 | class studentConstants { 15 | public: 16 | studentConstants(); 17 | 18 | }; 19 | 20 | extern const studentConstants g_student_constants; 21 | 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ipc/mmap/shmunlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../unpipc.h" 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | if (2 != argc) 14 | { 15 | fprintf(stderr, "usage: %s \n", argv[0]); 16 | exit(EXIT_FAILURE); 17 | } 18 | 19 | shm_unlink(argv[1]); 20 | 21 | exit(EXIT_SUCCESS); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /boost/demo_regex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | std::string line; 8 | boost::regex pat("^Subject: (Re: |Aw: )*(.*)"); 9 | 10 | while (std::cin) 11 | { 12 | std::getline(std::cin, line); 13 | boost::smatch matches; 14 | if (boost::regex_match(line, matches, pat)) 15 | { 16 | std::cout << matches[2] << std::endl; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/semunlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../unpipc.h" 10 | 11 | 12 | int main(int argc, char **argv) 13 | { 14 | if (argc != 2) 15 | { 16 | printf("usage: semunlink \n"); 17 | return -1; 18 | } 19 | 20 | sem_unlink(argv[1]); 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /pthread/README.md: -------------------------------------------------------------------------------- 1 | ##Pthread DEMO 2 | 3 | These 9 examples illustrate how to create a portabible multi-thread program. 4 | 5 | 1. pthread_hello.c 6 | 2. pthread_arg1.c 7 | 3. pthread_arg2.c 8 | 4. pthread_arg_error.c 9 | 5. pthread_stack.c 10 | 6. pthread_join.c 11 | 7. pthread_dotprod_serial.c 12 | 8. pthread_dotprod_mutex.c 13 | 9. pthread_condvar.c 14 | 15 | This article [POSIX Threads Programming](https://computing.llnl.gov/tutorials/pthreads/) explains more detailed the above 9 examples step by step. 16 | 17 | -------------------------------------------------------------------------------- /utility/zombie_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | pid_t pid; 9 | pid = fork(); 10 | if (pid < 0) 11 | { 12 | printf("error\n"); 13 | } 14 | else if (pid == 0) //child process 15 | { 16 | exit(0); 17 | } 18 | else //parent process 19 | { 20 | sleep(30); 21 | wait(NULL); //recycle the zombie process 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /cmake/t6/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 2 | ADD_EXECUTABLE(t6 ${SRC_LIST}) 3 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 4 | 5 | # 没有指定QUIET参数, HELLO_FIND_QUIETLY为假 6 | # 指定REQUIRED参数, HELLO_FIND_REQUIRED为真, 意味着此lib为该Project必须 7 | FIND_PACKAGE(HELLO REQUIRED) 8 | # 下面的HELLO_FOUND HELLO_INCLUDE_DIR HELLO_LIBRARY 9 | # 3个变量在FindHELLO.cmake中定义 10 | IF (HELLO_FOUND) 11 | INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR}) 12 | TARGET_LINK_LIBRARIES(t6 ${HELLO_LIBRARY}) 13 | ENDIF (HELLO_FOUND) 14 | 15 | -------------------------------------------------------------------------------- /protobuf/addressbook.proto: -------------------------------------------------------------------------------- 1 | message Person 2 | { 3 | required string name = 1; 4 | required int32 id = 2; 5 | optional string email = 3; 6 | 7 | enum PhoneType 8 | { 9 | MOBILE = 0; 10 | HOME = 1; 11 | WORK = 2; 12 | } 13 | 14 | message PhoneNumber 15 | { 16 | required string number = 1; 17 | optional PhoneType type = 2 [default = HOME]; 18 | } 19 | 20 | repeated PhoneNumber phone = 4; 21 | } 22 | 23 | message AddressBook 24 | { 25 | repeated Person person = 1; 26 | } 27 | -------------------------------------------------------------------------------- /py/log_basic/logging_format.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import logging 5 | 6 | #logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) 7 | #logging.basicConfig(format="%(asctime)s %(levelname)s:%(message)s", level=logging.DEBUG) 8 | logging.basicConfig(format="%(asctime)s %(levelname)s:%(message)s", level=logging.DEBUG, datefmt="%m/%d/%Y %I:%M:%S %p") 9 | 10 | logging.debug("This message should appear on the console") 11 | logging.info("So should this") 12 | logging.warning("Add this, too") 13 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_unlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | if (2 != argc) 10 | { 11 | fprintf(stderr, "usage: mq_unlink "); 12 | exit(-1); 13 | } 14 | 15 | 16 | // 每个消息队列有一个保存其当前打开着描述符数的引用计数器,当一个消息队列的 17 | // 引用计数仍大于0时, 其name就能删除,但是该队列的析构要到最后一个mq_close 18 | // 发生时才进行队列及其上的消息,一直存在到调用mq_unlink并让它的引用计数达 19 | // 到0以删除该队列为止 20 | mq_unlink(argv[1]); 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /utility/signal02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void sig_handler(int sig) 6 | { 7 | printf("\nouch, got a signal:%d\n", sig); 8 | signal(sig, SIG_DFL);//不恢复的话,ctrl + c就停不了程序了 9 | } 10 | 11 | 12 | int main() 13 | { 14 | struct sigaction act = {}; 15 | act.sa_handler = sig_handler; 16 | sigemptyset(&act.sa_mask); 17 | act.sa_flags = SA_RESETHAND; 18 | 19 | sigaction(SIGINT, &act, 0); 20 | while (1) 21 | { 22 | printf("hello world\n"); 23 | sleep(1); 24 | } 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /py/log_advanced/logging.conf: -------------------------------------------------------------------------------- 1 | [loggers] 2 | keys=root, config_with_file 3 | 4 | [handlers] 5 | keys=consoleHandler 6 | 7 | [formatters] 8 | keys=simpleFormatter 9 | 10 | [logger_root] 11 | level=DEBUG 12 | handlers=consoleHandler 13 | 14 | [logger_config_with_file] 15 | level=DEBUG 16 | handlers=consoleHandler 17 | qualname=config_with_file 18 | propagate=0 19 | 20 | [handler_consoleHandler] 21 | class=StreamHandler 22 | level=DEBUG 23 | formatter=simpleFormatter 24 | args=(sys.stdout,) 25 | 26 | [formatter_simpleFormatter] 27 | format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 28 | datefmt= 29 | 30 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/get_sys_conf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | long mq_open_max = sysconf(_SC_MQ_OPEN_MAX); 9 | 10 | // return -1 and errno == 0, means no definite limit 11 | if (-1 == mq_open_max && 0 != errno) 12 | { 13 | printf("sysconf return -1 and errno = %d\n", errno); 14 | printf("MQ_OPEN_MAX == -1 means no definite limit\n"); 15 | } 16 | 17 | printf("MQ_OPEN_MAX = %ld, MQ_PRIO_MAX = %ld\n", mq_open_max, 18 | sysconf(_SC_MQ_PRIO_MAX)); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/get_sys_conf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main(int argc, char **argv) 8 | { 9 | long sem_nsems_max = sysconf(_SC_SEM_NSEMS_MAX); 10 | 11 | // return -1 and errno == 0, means no definite limit 12 | if (-1 == sem_nsems_max) 13 | { 14 | printf("sysconf return -1 and errno = %d\n", errno); 15 | printf("SEM_NSEMS_MAX == -1 means no definite limit\n"); 16 | } 17 | 18 | printf("SEM_NSEMS_MAX = %ld, SEM_VALUE_MAX = %ld\n", 19 | sem_nsems_max, sysconf(_SC_SEM_VALUE_MAX)); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /ipc/mmap/pro_con.h: -------------------------------------------------------------------------------- 1 | #ifndef PRO_CON_H 2 | #define PRO_CON_H 3 | #include 4 | 5 | #define MESGSIZE 256 // max #bytes per message 6 | #define NMESG 16 // max #message 7 | 8 | struct shmstruct // struct stored in shared memory 9 | { 10 | sem_t mutex; 11 | sem_t nempty; 12 | sem_t nstored; 13 | int nput; // index into msgoff[] for next put 14 | long noverflow; // #overflows by senders 15 | sem_t noverflowmutex; // mutex for noverflow counter 16 | long msgoff[NMESG]; // offset in shared memory of each message 17 | char msgdata[NMESG * MESGSIZE]; // the actual messages 18 | }; 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /thrift/01/README.md: -------------------------------------------------------------------------------- 1 | the first demo to study thrift 2 | ================================ 3 | 4 | 1. `thrift -r --gen cpp student.thrift`, will generate some files in the folder gen-cpp/ 5 | 2. In the gen-cpp/ folder, you can use all of the files to build a server, I have modifed the file Serv\_server.skeleton.cpp to implement a simple\_server and nonblock\_server, and have the makefile done. 6 | 3. Also, there is a simple\_client and nonblock\_client implemented in the file client.cpp. 7 | 8 | **test instructions:** 9 | 10 | 1. start the server 11 | 2. start the client 12 | 3. you will see the obj sent by the client on the server side, printed out in the screen 13 | -------------------------------------------------------------------------------- /utility/strtok_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(int argc, char **argv) 6 | { 7 | char token_str[] = "hello world,this is a token example.Yes"; 8 | //char *token_str = "hello world,this is a token example.Yes"; this will not work 9 | char *pch = NULL; 10 | const char *delim = ", ."; 11 | 12 | printf("%s\n", token_str); 13 | 14 | //this interface will cast the delim char to '\0' 15 | pch = strtok(token_str, delim); 16 | while (pch != NULL) 17 | { 18 | printf("%s\n", pch); 19 | pch = strtok(NULL, delim); 20 | } 21 | //ps: the original str is modified!!!!! 22 | printf("%s\n", token_str); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /cmake/t3/lib_hello/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 2 | ADD_LIBRARY(hello_shared SHARED ${SRC_LIST}) # lib的名字不能重复 3 | ADD_LIBRARY(hello_static STATIC ${SRC_LIST}) 4 | SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello") 5 | SET_TARGET_PROPERTIES(hello_shared PROPERTIES OUTPUT_NAME "hello") 6 | 7 | # 设置动态库的版本号 8 | SET_TARGET_PROPERTIES(hello_shared PROPERTIES VERSION 1.2 SOVERSION 1) 9 | 10 | # 如果发现后来生成的lib清除了同名的早先生成的lib,(只有一个静态库或动态库生成) 11 | # 试下下面两个命令 12 | # 较新版本的cmake不再需要下面两个命令就可以同时生成hello.so hello.a 13 | #SET_TARGET_PROPERTIES(hello_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1) 14 | #SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) 15 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 16 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/semgetvalue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../unpipc.h" 11 | 12 | 13 | int main(int argc, char **argv) 14 | { 15 | sem_t *sem; 16 | int val; 17 | int ret = 0; 18 | 19 | if (argc != 2) 20 | { 21 | printf("usage: semgetvalue \n"); 22 | return -1; 23 | } 24 | 25 | sem = sem_open(argv[1], 0); 26 | assert(SEM_FAILED != sem); 27 | 28 | ret = sem_getvalue(sem, &val); 29 | assert(-1 != ret); 30 | printf("value = %d\n", val); 31 | 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /utility/print_backtrace.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void myfunc3(void) 7 | { 8 | int j, nptrs; 9 | #define SIZE 100 10 | void *buffer[100]; 11 | char **string; 12 | 13 | nptrs = backtrace(buffer, SIZE); 14 | printf("backtrace() returned %d addresses\n", nptrs); 15 | 16 | // backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO); 17 | string = backtrace_symbols(buffer, nptrs); 18 | for (j = 0; j < nptrs; j++) 19 | { 20 | printf("%s\n", string[j]); 21 | } 22 | free(string); 23 | } 24 | 25 | void myfunc(void) 26 | { 27 | myfunc3(); 28 | } 29 | 30 | int main(int argc, char **argv) 31 | { 32 | myfunc(); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/sempost.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../unpipc.h" 11 | 12 | 13 | int main(int argc, char **argv) 14 | { 15 | sem_t *sem; 16 | int val; 17 | int ret = 0; 18 | 19 | if (argc != 2) 20 | { 21 | printf("usage: sempost \n"); 22 | return -1; 23 | } 24 | 25 | sem = sem_open(argv[1], 0); 26 | assert(SEM_FAILED != sem); 27 | sem_post(sem); 28 | 29 | ret = sem_getvalue(sem, &val); 30 | assert(-1 != ret); 31 | printf("value = %d\n", val); 32 | 33 | return 0; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/makefile: -------------------------------------------------------------------------------- 1 | FLAGS = -Wall -g 2 | 3 | all: semcreate semunlink semgetvalue semwait sempost get_sys_conf 4 | 5 | semcreate: semcreate.c 6 | gcc $(FLAGS) semcreate.c -o semcreate -pthread 7 | 8 | semunlink: semunlink.c 9 | gcc $(FLAGS) semunlink.c -o semunlink -pthread 10 | 11 | semgetvalue: semgetvalue.c 12 | gcc $(FLAGS) semgetvalue.c -o semgetvalue -pthread 13 | 14 | semwait: semwait.c 15 | gcc $(FLAGS) semwait.c -o semwait -pthread 16 | 17 | sempost: sempost.c 18 | gcc $(FLAGS) sempost.c -o sempost -pthread 19 | 20 | get_sys_conf: get_sys_conf.c 21 | gcc $(FLAGS) get_sys_conf.c -o get_sys_conf 22 | 23 | clean: 24 | rm -f semcreate 25 | rm -f semunlink 26 | rm -f semgetvalue 27 | rm -f semwait 28 | rm -f sempost 29 | rm -f get_sys_conf 30 | -------------------------------------------------------------------------------- /cmake/t5/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 2 | ADD_EXECUTABLE(curltest ${SRC_LIST}) 3 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 4 | #INCLUDE_DIRECTORIES(/usr/include) 5 | #TARGET_LINK_LIBRARIES(curltest curl) 6 | FIND_PACKAGE(CURL) 7 | IF (CURL_FOUND) 8 | MESSAGE(STATUS "CURL_INCLUDE_DIR: " ${CURL_INCLUDE_DIR} " CURL_LIBRARY: " ${CURL_LIBRARY}) 9 | INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) 10 | TARGET_LINK_LIBRARIES(curltest ${CURL_LIBRARY}) 11 | ELSE(CURL_FOUND) 12 | MESSAGE(FATAL_ERROR "CURL library not found") 13 | ENDIF(CURL_FOUND) 14 | 15 | #对于系统预定义的Find.cmake模块,使用方法一般如上所示: 16 | #每一个模块都会定义以下几个变量 17 | #• _FOUND 通过此变量判断模块是否被找到 18 | #• _INCLUDE_DIR or _INCLUDES 19 | #• _LIBRARY or _LIBRARIES 20 | -------------------------------------------------------------------------------- /utility/byteorder.c: -------------------------------------------------------------------------------- 1 | /* 2 | *filename:byteorder.c 3 | *author:carl 4 | *function: tell the host byteorder 5 | *date:2014.02.21 6 | * */ 7 | 8 | 9 | #include 10 | #include 11 | 12 | int main(int argc, char **argv) 13 | { 14 | union 15 | { 16 | short s; 17 | char c[sizeof(short)]; 18 | } un; 19 | 20 | un.s = 0x0102; 21 | if (sizeof(short) == 2) 22 | { 23 | if (un.c[0] == 1 && un.c[1] == 2) 24 | printf("big-endian\n"); 25 | if (un.c[0] == 2 && un.c[1] == 1) 26 | printf("little-endian\n"); 27 | else 28 | printf("unknown\n"); 29 | } 30 | else 31 | { 32 | printf("sizeof(short) = %d\n", sizeof(short)); 33 | } 34 | 35 | exit(0); 36 | } 37 | -------------------------------------------------------------------------------- /py/log_advanced/logging_config_in_code.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import logging 5 | 6 | # create logger 7 | logger = logging.getLogger("simple_config") 8 | logger.setLevel(logging.DEBUG) 9 | 10 | # create console handler and set level to debug 11 | ch = logging.StreamHandler() 12 | ch.setLevel(logging.DEBUG) 13 | 14 | # create formatter 15 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 16 | 17 | # add formatter to ch 18 | ch.setFormatter(formatter) 19 | 20 | # add ch to logger 21 | logger.addHandler(ch) 22 | 23 | # 'application' code 24 | logger.debug("debug message") 25 | logger.info("info message") 26 | logger.warn("warn message") 27 | logger.error("error message") 28 | logger.critical("critical message") 29 | -------------------------------------------------------------------------------- /py/demo_time.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding:utf-8 -*- 3 | 4 | import time 5 | 6 | ''' 7 | python中时间日期格式化符号: 8 | %y 两位数的年份表示(00-99) 9 | %Y 四位数的年份表示(000-9999) 10 | %m 月份(01-12) 11 | %d 月内中的一天(0-31) 12 | %H 24小时制小时数(0-23) 13 | %I 12小时制小时数(01-12) 14 | %M 分钟数(00=59) 15 | %S 秒(00-59) 16 | 17 | %a 本地简化星期名称 18 | %A 本地完整星期名称 19 | %b 本地简化的月份名称 20 | %B 本地完整的月份名称 21 | %c 本地相应的日期表示和时间表示 22 | %j 年内的一天(001-366) 23 | %p 本地A.M.或P.M.的等价符 24 | %U 一年中的星期数(00-53)星期天为星期的开始 25 | %w 星期(0-6),星期天为星期的开始 26 | %W 一年中的星期数(00-53)星期一为星期的开始 27 | %x 本地相应的日期表示 28 | %X 本地相应的时间表示 29 | %Z 当前时区的名称 30 | %% %号本身 31 | ''' 32 | 33 | # unix time stamp 34 | print time.time() 35 | 36 | # full time info 37 | print time.localtime(time.time()) 38 | 39 | # formatted time 40 | print time.strftime('%Y-%m-%d',time.localtime(time.time())) 41 | -------------------------------------------------------------------------------- /utility/atexit_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void my_exit1(void); 5 | static void my_exit2(void); 6 | 7 | int main(int argc, char **argv) 8 | { 9 | if (atexit(my_exit2) != 0) 10 | { 11 | printf("register exit2 error\n"); 12 | exit(1); 13 | } 14 | if (atexit(my_exit1) != 0) 15 | { 16 | printf("register exit1 error 1\n"); 17 | exit(2); 18 | } 19 | if (atexit(my_exit1) != 0) 20 | { 21 | printf("register exit1 error 2\n"); 22 | exit(3); 23 | } 24 | 25 | printf("main is done\n"); 26 | return 0; 27 | } 28 | 29 | static void my_exit1(void) 30 | { 31 | printf("my exit1 handler\n"); 32 | } 33 | 34 | static void my_exit2(void) 35 | { 36 | printf("my exit2 handler\n"); 37 | } 38 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/semwait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../unpipc.h" 11 | 12 | 13 | int main(int argc, char **argv) 14 | { 15 | sem_t *sem; 16 | int val; 17 | int ret = 0; 18 | 19 | if (argc != 2) 20 | { 21 | printf("usage: semwait \n"); 22 | return -1; 23 | } 24 | 25 | sem = sem_open(argv[1], 0); 26 | assert(SEM_FAILED != sem); 27 | 28 | sem_wait(sem); 29 | ret = sem_getvalue(sem, &val); 30 | assert(-1 != ret); 31 | printf("pid %ld has semaphore, value = %d\n", (long)getpid(), val); 32 | 33 | pause(); 34 | return 0; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /py/log_advanced/logging_rotate_by_size.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import glob 5 | import logging 6 | import logging.handlers 7 | 8 | LOG_FILENAME = 'logging_rotatingfile_by_size.out' 9 | 10 | # Set up a specific logger with our desired output level 11 | my_logger = logging.getLogger('MyLogger') 12 | my_logger.setLevel(logging.DEBUG) 13 | 14 | # Add the log message handler to the logger 15 | handler = logging.handlers.RotatingFileHandler( 16 | LOG_FILENAME, maxBytes=20, backupCount=5) 17 | 18 | my_logger.addHandler(handler) 19 | 20 | # Log some messages 21 | for i in range(20): 22 | my_logger.debug('i = %d' % i) 23 | 24 | # See what files are created 25 | logfiles = glob.glob('%s*' % LOG_FILENAME) 26 | 27 | for filename in logfiles: 28 | print(filename) 29 | -------------------------------------------------------------------------------- /testcode/inherited_virtual_func.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 1. 测试两个具有继承关系的Class在通过基类的指针和引用来调用虚函数的表现 3 | * 2. 测试默认参数传递的表现 4 | * 5 | * 注意观察使用默认参数和传递实参的时候程序分别如何表现 6 | * 7 | * */ 8 | 9 | #include 10 | 11 | using namespace std; 12 | 13 | class Base 14 | { 15 | public: 16 | virtual void Fun(int number = 10) 17 | { 18 | std::cout << "Base::Fun with number " << number <Fun(); 44 | c->Fun(40); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /ipc/mmap/shmwrite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../unpipc.h" 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int i, fd; 14 | struct stat stat; 15 | unsigned char *ptr = NULL; 16 | 17 | if (2 != argc) 18 | { 19 | fprintf(stderr, "usage: %s \n", argv[0]); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | fd = shm_open(argv[1], O_RDWR, FILE_MODE); 24 | fstat(fd, &stat); 25 | 26 | ptr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 27 | close(fd); 28 | 29 | // set: ptr[i] = i 30 | for (i = 0; i < stat.st_size; ++i) 31 | { 32 | *ptr++ = i % 256; 33 | } 34 | 35 | exit(EXIT_SUCCESS); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /cmake/t5/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | FILE *fp; 7 | 8 | int write_data(void *ptr, size_t size, size_t nmemb, void *stream) 9 | { 10 | int written = fwrite(ptr, size, nmemb, (FILE *)fp); 11 | return written; 12 | } 13 | 14 | 15 | // 通过curl取回www.linux-ren.org的首页并写入/tmp/curl-test文件中 16 | int main() 17 | { 18 | const char *path = "tmp/curl-test"; 19 | const char *mode = "w"; 20 | 21 | fp = fopen(path, mode); 22 | curl_global_init(CURL_GLOBAL_ALL); 23 | CURLcode res; 24 | CURL *curl = curl_easy_init(); 25 | curl_easy_setopt(curl, CURLOPT_URL, "http://www.linux-ren.org"); 26 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 27 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 28 | res = curl_easy_perform(curl); 29 | 30 | curl_easy_cleanup(curl); 31 | } 32 | -------------------------------------------------------------------------------- /utility/chdir_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(void) 6 | { 7 | char cur_working_dir[256] = {0}; 8 | 9 | //get current working directory, getcwd return buf(cur_working_dir) if success, else return NULL 10 | if (NULL == getcwd(cur_working_dir, sizeof(cur_working_dir))) 11 | { 12 | printf("getcwd error\n"); 13 | return -1; 14 | } 15 | printf("current working dir:%s\n", cur_working_dir); 16 | 17 | //change current working directory to buf '/tmp' 18 | if (0 != chdir("/tmp")) 19 | { 20 | printf("chdir error\n"); 21 | return -2; 22 | } 23 | 24 | if (NULL == getcwd(cur_working_dir, sizeof(cur_working_dir))) 25 | { 26 | printf("getcwd error 2\n"); 27 | return -1; 28 | } 29 | printf("after chdir, current working dir:%s\n", cur_working_dir); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /utility/getopt_test.c: -------------------------------------------------------------------------------- 1 | /*================================================================ 2 | * Copyright (C) 2014 All rights reserved. 3 | * 4 | * FileName:getopt_test.c 5 | * Author :Carl 6 | * Creat Date:2014.03.06 7 | * Description: 8 | * 9 | ================================================================*/ 10 | #include 11 | #include 12 | 13 | 14 | int main(int argc, char **argv) 15 | { 16 | char o; 17 | while (-1 != (o = getopt(argc, argv, "f:h"))) 18 | { 19 | switch (o) 20 | { 21 | case 'f': 22 | printf("option f\n"); 23 | printf("f followed by:%s\n", optarg); 24 | break; 25 | case 'h': 26 | printf("option h\n"); 27 | break; 28 | default: 29 | printf("o is %c\n", o); 30 | break; 31 | } 32 | } 33 | 34 | return 0; 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /testcode/check_os.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 该示例实现两个功能 3 | * 1. 测试系统多多少位 4 | * 2. 测试系统默认字节序时大端还是小端 5 | */ 6 | 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main() 12 | { 13 | 14 | // 判断当前系统是多少位 15 | char *a = NULL; 16 | 17 | if (4 == sizeof(void *)) 18 | { 19 | cout << "os is 32 bit" < 2 | #include 3 | #include 4 | 5 | #define NUM_THREADS 5 6 | 7 | 8 | void *PrintHello(void *threadid) 9 | { 10 | long tid; 11 | tid = (long)threadid; 12 | printf("Hello World! It's me, thread #%ld!\n", tid); 13 | pthread_exit(NULL); 14 | } 15 | 16 | int main(int argc, char **argv) 17 | { 18 | pthread_t threads[NUM_THREADS]; 19 | int rc; 20 | long t; 21 | for (t=0; t 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../unpipc.h" 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int i, fd; 14 | struct stat stat; 15 | unsigned char c, *ptr = NULL; 16 | 17 | if (2 != argc) 18 | { 19 | fprintf(stderr, "usage: %s \n", argv[0]); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | fd = shm_open(argv[1], O_RDONLY, FILE_MODE); 24 | fstat(fd, &stat); 25 | 26 | ptr = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); 27 | close(fd); 28 | 29 | // set: ptr[i] = i 30 | for (i = 0; i < stat.st_size; ++i) 31 | { 32 | if ((c = *ptr++) != (i % 256)) 33 | { 34 | fprintf(stderr, "ptr[%d] = %d\n", i, c); 35 | exit(EXIT_FAILURE); 36 | } 37 | } 38 | 39 | exit(EXIT_SUCCESS); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /network/sockclient2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *agrv[]) 9 | { 10 | struct sockaddr_in server_addr = {}; 11 | int server_len = 0; 12 | int sockfd = -1; 13 | int result = 0; 14 | char c = 'A'; 15 | 16 | //创建数据报套接字 17 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 18 | 19 | //设置服务器IP端口 20 | server_addr.sin_family = AF_INET; 21 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 22 | server_addr.sin_port = htons(9739); 23 | server_len = sizeof(server_addr); 24 | 25 | //向服务器发送数据 26 | sendto(sockfd, &c, sizeof(char), 0, (struct sockaddr *)&server_addr, server_len); 27 | 28 | //接收服务器处理后发送过来的数据,由于不关心数据来源,所以把后面两个参数设置为0 29 | recvfrom(sockfd, &c, sizeof(char), 0, 0, 0); 30 | printf("char from the server = %c\n", c); 31 | 32 | close(sockfd); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ipc/fcntl/lock_main.c: -------------------------------------------------------------------------------- 1 | #include "lock_define.h" 2 | 3 | #define FILE_MODE (S_IRUSR | S_IWUSR | S_ISGID | S_IROTH) 4 | static const char *SEQFILE = "seqno"; 5 | #define MAXLINE 80 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int fd; 10 | long i, seqno; 11 | pid_t pid; 12 | ssize_t n; 13 | char line[MAXLINE+1] = {}; 14 | 15 | pid = getpid(); 16 | fd = open(SEQFILE, O_RDWR, FILE_MODE); 17 | 18 | for (i=0; i<20; ++i) 19 | { 20 | write_lock(fd, 0, SEEK_SET, 0); 21 | lseek(fd, 0L, SEEK_SET); 22 | n = read(fd, line, MAXLINE); 23 | line[n] = 0; 24 | 25 | n = sscanf(line, "%ld\n", &seqno); 26 | printf("%s: pid = %ld, seq# = %ld\n", argv[0], (long)pid, seqno); 27 | ++seqno; 28 | 29 | snprintf(line, sizeof(line), "%ld\n", seqno); 30 | lseek(fd, 0L, SEEK_SET); 31 | write(fd, line, strlen(line)); 32 | 33 | un_lock(fd, 0, SEEK_SET, 0); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /testcode/class_bytes_align.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 测试class中不同成员对sizeof的影响,尤其需要注意虚函数,指针,字节对齐几个方面 3 | * 可以通过对代码中相应部分进行注释,重新编译,来观察不同成员所产生的影响 4 | * 5 | */ 6 | 7 | #include 8 | 9 | using namespace std; 10 | 11 | 12 | class Base 13 | { 14 | public: 15 | Base(); 16 | virtual ~Base(); //每个实例都有虚函数表 17 | void set_num(int num) //普通成员函数,为各实例公有,不归入sizeof统计 18 | { 19 | a=num; 20 | } 21 | private: 22 | int a; //占4字节 23 | char *p; //4字节指针(32位系统) 24 | }; 25 | 26 | class Derive:public Base 27 | { 28 | public: 29 | Derive():Base(){}; 30 | ~Derive(){}; 31 | private: 32 | static int st; //非实例独占 33 | int d; //占4字节 34 | char *p; //4字节指针(32位系统) 35 | char c; 36 | 37 | }; 38 | 39 | int main() 40 | { 41 | cout <<"sizeof(Base) is " < 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../unpipc.h" 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int c, fd, flags; 14 | char *ptr = NULL; 15 | off_t length; 16 | 17 | flags = O_RDWR | O_CREAT; 18 | 19 | while ((c = getopt(argc, argv, "e")) != -1) 20 | { 21 | switch (c) 22 | { 23 | case 'e': 24 | flags |= O_EXCL; 25 | break; 26 | } 27 | } 28 | 29 | if (optind != argc - 2) 30 | { 31 | fprintf(stderr, "usage: %s [-e] \n", argv[0]); 32 | exit(EXIT_FAILURE); 33 | } 34 | length = atoi(argv[optind + 1]); 35 | 36 | fd = shm_open(argv[optind], flags, FILE_MODE); 37 | ftruncate(fd, length); 38 | 39 | ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 40 | 41 | exit(EXIT_SUCCESS); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /ipc/mmap/count03_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../unpipc.h" 10 | 11 | 12 | #define SEM_NAME "mysem" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | int fd, i, nloop; 17 | pid_t pid; 18 | int *ptr = NULL; 19 | sem_t *mutex; 20 | 21 | if (3 != argc) 22 | { 23 | fprintf(stderr, "pls usage: %s <#nloops>\n", argv[0]); 24 | exit(EXIT_FAILURE); 25 | } 26 | nloop = atoi(argv[2]); 27 | 28 | fd = shm_open(argv[1], O_RDWR, FILE_MODE); 29 | ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 30 | close(fd); 31 | 32 | mutex = sem_open(SEM_NAME, 0); 33 | 34 | pid = getpid(); 35 | 36 | for (i = 0; i < nloop; ++i) 37 | { 38 | sem_wait(mutex); 39 | printf("pid %ld: %d\n", (long)pid, (*ptr)++); 40 | sem_post(mutex); 41 | } 42 | exit(EXIT_SUCCESS); 43 | } 44 | -------------------------------------------------------------------------------- /py/log_advanced/logging_rotate_by_time.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import glob 5 | import time 6 | import logging 7 | import logging.handlers 8 | 9 | LOG_FILENAME = 'logging_rotatingfile_by_time.out' 10 | 11 | # Set up a specific logger with our desired output level 12 | my_logger = logging.getLogger('MyLogger') 13 | my_logger.setLevel(logging.DEBUG) 14 | 15 | # Add the log message handler to the logger 16 | # when - S--second 17 | # M--Minute 18 | # H--Hour default 19 | # D--Day 20 | # W{0-6}--roll over on a certain day: 0-Monday 21 | # midnight--roll over at midnight 22 | # interval: 1 default 23 | 24 | handler = logging.handlers.TimedRotatingFileHandler( 25 | LOG_FILENAME, when='S', interval=1, backupCount=20) 26 | 27 | my_logger.addHandler(handler) 28 | 29 | # Log some messages 30 | for i in range(20): 31 | my_logger.debug('i = %d' % i) 32 | time.sleep(1) 33 | 34 | # See what files are created 35 | logfiles = glob.glob('%s*' % LOG_FILENAME) 36 | 37 | for filename in logfiles: 38 | print(filename) 39 | -------------------------------------------------------------------------------- /ipc/mmap/count03_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../unpipc.h" 10 | 11 | 12 | #define SEM_NAME "mysem" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | int fd; 17 | sem_t *mutex; 18 | int *ptr = NULL; 19 | 20 | if (2 != argc) 21 | { 22 | fprintf(stderr, "usage: %s \n", argv[0]); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | shm_unlink(argv[1]); 27 | // open file, initialize to 0, map into memory 28 | fd = shm_open(argv[1], O_RDWR | O_CREAT | O_EXCL, FILE_MODE); 29 | ftruncate(fd, sizeof(int)); 30 | 31 | // 1. mmap 2. fork 32 | ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 33 | close(fd); 34 | 35 | sem_unlink(SEM_NAME); 36 | // create, initialize and unlink semaphore 37 | mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1); 38 | sem_close(mutex); 39 | 40 | exit(EXIT_SUCCESS); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /utility/signal04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void sig_handler(int sig) 6 | { 7 | printf("\nouch, got a signal:%d\n", sig); 8 | } 9 | 10 | 11 | int main() 12 | { 13 | sigset_t sigset = {}; 14 | sigset_t ign_set = {}; 15 | struct sigaction act = {}; 16 | 17 | sigemptyset(&sigset); 18 | sigemptyset(&ign_set); 19 | sigaddset(&sigset, SIGINT); 20 | 21 | act.sa_handler= sig_handler; 22 | sigemptyset(&act.sa_mask); 23 | act.sa_flags = 0; 24 | sigaction(SIGINT, &act, 0); 25 | 26 | printf("waiting for the signal SIGINIT.......\n"); 27 | pause(); 28 | 29 | sigprocmask(SIG_SETMASK, &sigset, 0); 30 | printf("press ctrl C in 10 s....\n"); 31 | sleep(10); 32 | 33 | sigpending(&ign_set); 34 | if (sigismember(&ign_set, SIGINT)) 35 | printf("SIGINT is ignored\n"); 36 | 37 | sigdelset(&sigset, SIGINT); 38 | printf("wait for the SIGINT signal\n"); 39 | sigsuspend(&sigset); 40 | 41 | printf("exit in 5 s\n"); 42 | sleep(5); 43 | 44 | return 0; 45 | 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /ipc/pipe/pipe02.c: -------------------------------------------------------------------------------- 1 | /* 2 | popen函数,FILE *popen(const char *command, const char *type); 3 | 创建一个管道并启动另外一个进程(command命令),该进程要么从该管 4 | 道读出标准输入(type为"w"),要么往该管道写入标准输出(type 为"r") 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char **argv) 12 | { 13 | FILE *read_fp = NULL; 14 | FILE *write_fp = NULL; 15 | char buffer[BUFSIZ + 1] = {}; 16 | int chars_read = 0; 17 | 18 | read_fp = popen("ls -l /home/carl", "r"); 19 | write_fp = popen("grep rwxrwxr-x", "w"); 20 | 21 | if (read_fp && write_fp) 22 | { 23 | chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); 24 | while (chars_read) 25 | { 26 | buffer[chars_read] = 0; 27 | printf("read buffer:%s\n", buffer); 28 | fwrite(buffer, sizeof(char), chars_read, write_fp); 29 | chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); 30 | } 31 | 32 | pclose(read_fp); 33 | pclose(write_fp); 34 | exit(EXIT_SUCCESS); 35 | } 36 | 37 | exit(EXIT_FAILURE); 38 | } 39 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_send.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int main(int argc, char **argv) 11 | { 12 | mqd_t mqd; 13 | void *ptr = NULL; 14 | size_t len; 15 | unsigned int prio; 16 | int ret = 0; 17 | 18 | if (argc != 4) 19 | { 20 | fprintf(stdout, "usage: mq_send <#byte> \n"); //优先级priority不能高于MQ_PRIO_MAX的值 21 | exit(-1); 22 | } 23 | 24 | len = atoi(argv[2]); 25 | prio = atoi(argv[3]); 26 | 27 | mqd = mq_open(argv[1], O_WRONLY); 28 | if (-1 == mqd) 29 | { 30 | fprintf(stdout, "mq_open error:%d\n", errno); 31 | } 32 | 33 | ptr = calloc(len, sizeof(char)); 34 | if (NULL == ptr) 35 | { 36 | fprintf(stdout, "calloc error\n"); 37 | exit(-1); 38 | } 39 | 40 | ret = mq_send(mqd, ptr, len, prio); 41 | if (-1 == ret) 42 | { 43 | fprintf(stdout, "mq_send error:%d\n", errno); 44 | exit(-1); 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /ipc/fcntl/lock_define.c: -------------------------------------------------------------------------------- 1 | #include "lock_define.h" 2 | #include "../unpipc.h" 3 | 4 | static const char *SEQFILE = "seqno"; 5 | 6 | int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) 7 | { 8 | struct flock lock; 9 | 10 | //lock = {F_WRLCK, SEEK_SET, 0, 0, 0}; 11 | // 这种用法是错误的,Posix只是定义了一个struct中的必须成员,各个实现可以以 12 | // 任意顺序来排列这些成员,还可以增设特定于实现的成员 13 | 14 | // 一定要以这种方式来进行初始化操作 15 | lock.l_type = type; 16 | lock.l_whence = whence; 17 | lock.l_start = offset; 18 | lock.l_len = len; 19 | 20 | return fcntl(fd, cmd, &lock); 21 | } 22 | 23 | pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len) 24 | { 25 | struct flock lock; 26 | 27 | lock.l_type = type; 28 | lock.l_whence = whence; 29 | lock.l_start = offset; 30 | lock.l_len = len; 31 | 32 | if (-1 == fcntl(fd, F_SETLK, &lock)) 33 | { 34 | return -1; 35 | } 36 | 37 | if (F_UNLCK == lock.l_type) 38 | { 39 | return 0; // false, region not locked by another proc 40 | } 41 | 42 | return lock.l_pid; // true, return positive PID of lock owner 43 | } 44 | 45 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/makefile: -------------------------------------------------------------------------------- 1 | FLAGS = -g -Wall 2 | 3 | all: mq_create mq_unlink mq_send mq_recv get_sys_conf mq_notify01 mq_notify02 mq_notify03 mq_notify04 signal_realtime 4 | 5 | 6 | mq_create: mq_create.c 7 | gcc $(FLAGS) mq_create.c -o mq_create -lrt 8 | 9 | mq_unlink: mq_unlink.c 10 | gcc $(FLAGS) mq_unlink.c -o mq_unlink -lrt 11 | 12 | mq_send: mq_send.c 13 | gcc $(FLAGS) mq_send.c -o mq_send -lrt 14 | mq_recv: mq_recv.c 15 | gcc $(FLAGS) mq_recv.c -o mq_recv -lrt 16 | 17 | get_sys_conf: get_sys_conf.c 18 | gcc $(FLAGS) get_sys_conf.c -o get_sys_conf 19 | 20 | mq_notify01: mq_notify01.c 21 | gcc $(FLAGS) mq_notify01.c -o mq_notify01 -lrt 22 | 23 | mq_notify02: mq_notify02.c 24 | gcc $(FLAGS) mq_notify02.c -o mq_notify02 -lrt 25 | 26 | mq_notify03: mq_notify03.c 27 | gcc $(FLAGS) mq_notify03.c -o mq_notify03 -lrt 28 | 29 | mq_notify04: mq_notify04.c 30 | gcc $(FLAGS) mq_notify04.c -o mq_notify04 -lrt 31 | 32 | signal_realtime: signal_realtime.c 33 | gcc $(FLAGS) signal_realtime.c -o signal_realtime 34 | 35 | clean: 36 | rm -f mq_create mq_unlink mq_send mq_recv get_sys_conf mq_notify01 mq_notify02 mq_notify03 mq_notify04 signal_realtime 37 | 38 | -------------------------------------------------------------------------------- /cmake/t6/cmake/FindHELLO.cmake: -------------------------------------------------------------------------------- 1 | # 注意此cmake文件中的3个变量名 2 | # HELLO_INCLUDE_DIR -- _INCLUDE_DIR 3 | # HELLO_LIBRARY -- _LIBRARY 4 | # HELLO_FOUND -- _FOUND 5 | # 惯例需要定义这3个变量,命名规则如上,以便与cmake预定义的cmake模块中的变量名统一 6 | 7 | # FIND_PATH和FIND_LIBARY的path部分,一定要是.h文件和lib文件所在的当前目录,否则找不到 8 | FIND_PATH(HELLO_INCLUDE_DIR hello.h /home/carl/cmake/t3/lib_hello) 9 | MESSAGE(STATUS "HELLO_INCLUDE_DIR: " ${HELLO_INCLUDE_DIR}) 10 | 11 | FIND_LIBRARY(HELLO_LIBRARY hello /home/carl/cmake/t3/build/lib) 12 | MESSAGE(STATUS "HELLO_LIBRARY: " ${HELLO_LIBRARY}) 13 | 14 | 15 | IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY) 16 | SET(HELLO_FOUND TRUE) 17 | ENDIF(HELLO_INCLUDE_DIR AND HELLO_LIBRARY) 18 | 19 | IF (HELLO_FOUND) 20 | # 若FIND_PACKAGE命令没有指定QUIET参数,那下面的IF语句就为真 21 | IF (NOT HELLO_FIND_QUIETLY) 22 | MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}") 23 | ENDIF (NOT HELLO_FIND_QUIETLY) 24 | ELSE (HELLO FOUND) 25 | # 如果FIND_PACKAGE命令指定了REQUIRED参数,说明这个库是此Project必须的 26 | # 对应下面的HELLO_FIND_REQUIRED变量 27 | IF (HELLO_FIND_REQUIRED) 28 | MESSAGE(FATAL_ERROR "Could not find hello library") 29 | ENDIF (HELLO_FIND_REQUIRED) 30 | ENDIF (HELLO_FOUND) 31 | 32 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/semcreate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../unpipc.h" 11 | 12 | 13 | int main(int argc, char **argv) 14 | { 15 | int c, flags; 16 | sem_t *sem; 17 | unsigned int value; 18 | 19 | flags = O_RDWR | O_CREAT; 20 | value = 1; 21 | 22 | c = getopt(argc, argv, "ei:"); 23 | while (-1 != c) 24 | { 25 | switch (c) 26 | { 27 | case 'e': 28 | flags |= O_EXCL; 29 | break; 30 | 31 | case 'i': 32 | value = atoi(optarg); 33 | break; 34 | } 35 | } 36 | 37 | if (optind != (argc - 1)) 38 | { 39 | printf("usage: semcreate [-e] [-i initalvalue] \n"); 40 | return -1; 41 | } 42 | 43 | sem = sem_open(argv[optind], flags, FILE_MODE, value); 44 | assert(SEM_FAILED != sem); 45 | 46 | //如果忘记sem_close, 当进程终止时,该信号量也被关闭(所占用的系统资源随之 47 | //释放),但它的值仍然保持 48 | sem_close(sem); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /network/sockclient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int sockfd = -1; 12 | int len = 0; 13 | struct sockaddr_in address = {}; 14 | int result = 0; 15 | char ch = 'A'; //data to send 16 | char recv[5] = {}; 17 | int recv_len = 0; 18 | 19 | //创建流套接字 20 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 21 | 22 | //设置要连接的服务器信息 23 | address.sin_family = AF_INET; 24 | address.sin_addr.s_addr = inet_addr("127.0.0.1"); 25 | address.sin_port = htons(8002); 26 | 27 | len = sizeof(address); 28 | 29 | //连接到服务器 30 | result = connect(sockfd, (struct sockaddr *)&address, len); 31 | 32 | if (result == -1) 33 | { 34 | perror("ops:client\n"); 35 | exit(1); 36 | } 37 | 38 | //发送请求给服务器 39 | write(sockfd, &ch, 1); 40 | 41 | //从服务器获取数据 42 | while (1) 43 | { 44 | recv_len = read(sockfd, recv, 4); 45 | if (recv_len <= 0) 46 | break; 47 | printf("data from server = %s \n", recv); 48 | } 49 | close(sockfd); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /utility/jump_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TOK_ADD 5 5 | #define MAXLINE 40 6 | 7 | jmp_buf jmpbuffer; 8 | char *tok_ptr; 9 | 10 | void do_line(char *ptr); 11 | void cmd_add(void); 12 | int get_token(void); 13 | 14 | int main(int argc, char **argv) 15 | { 16 | char line[MAXLINE]; 17 | int ret = 0; 18 | 19 | if ((ret = setjmp(jmpbuffer)) != 0) //类似于goto所用的tag,告诉longjmp应该返回到哪里 20 | { 21 | printf("error:%d\n", ret); 22 | } 23 | 24 | while (fgets(line, MAXLINE, stdin) != NULL) 25 | { 26 | do_line(line); 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | 33 | 34 | void do_line(char *ptr) 35 | { 36 | int cmd; 37 | 38 | tok_ptr = ptr; 39 | while ((cmd = get_token()) > 0) 40 | { 41 | switch (cmd) 42 | case TOK_ADD: 43 | cmd_add(); 44 | printf("cmd add complete\n"); //this will not be printed out 45 | break; 46 | } 47 | } 48 | 49 | void cmd_add(void) 50 | { 51 | int token; 52 | token = get_token(); 53 | if (token > 0) 54 | { 55 | longjmp(jmpbuffer, 2); //第2个参数“2”,会是setjmp的返回值 56 | } 57 | } 58 | 59 | int get_token(void) 60 | { 61 | return TOK_ADD; 62 | } 63 | -------------------------------------------------------------------------------- /ipc/mmap/makefile: -------------------------------------------------------------------------------- 1 | FLAGS = -Wall -g 2 | 3 | all: count01 count02 shmcreate shmunlink shmread shmwrite count03_client count03_server producer consumer 4 | 5 | count01: count01.c 6 | gcc $(FLAGS) count01.c -o count01 -pthread 7 | 8 | count02: count02.c 9 | gcc $(FLAGS) count02.c -o count02 -pthread 10 | 11 | shmcreate: shmcreate.c 12 | gcc $(FLAGS) shmcreate.c -o shmcreate -lrt 13 | 14 | shmunlink: shmunlink.c 15 | gcc $(FLAGS) shmunlink.c -o shmunlink -lrt 16 | 17 | shmread: shmread.c 18 | gcc $(FLAGS) shmread.c -o shmread -lrt 19 | 20 | shmwrite: shmwrite.c 21 | gcc $(FLAGS) shmwrite.c -o shmwrite -lrt 22 | 23 | count03_server: count03_server.c 24 | gcc $(FLAGS) count03_server.c -o count03_server -lrt -pthread 25 | 26 | count03_client: count03_client.c 27 | gcc $(FLAGS) count03_client.c -o count03_client -lrt -pthread 28 | 29 | producer: producer.c 30 | gcc $(FLAGS) producer.c -o producer -lrt -pthread 31 | 32 | consumer: consumer.c 33 | gcc $(FLAGS) consumer.c -o consumer -lrt -pthread 34 | 35 | clean: 36 | rm -f count01 37 | rm -f count02 38 | rm -f shmcreate 39 | rm -f shmunlink 40 | rm -f shmread 41 | rm -f shmwrite 42 | rm -f count03_client 43 | rm -f count03_server 44 | rm -f producer 45 | rm -f consumer 46 | 47 | 48 | -------------------------------------------------------------------------------- /py/log_advanced/logging_rotate_on_restart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import os 5 | import glob 6 | import logging 7 | import logging.handlers 8 | import time 9 | 10 | LOG_FILENAME = 'logging_rotatingfile_example.out' 11 | 12 | # Set up a specific logger with our desired output level 13 | my_logger = logging.getLogger('MyLogger') 14 | my_logger.setLevel(logging.DEBUG) 15 | 16 | # Check if log exists and should therefore be rolled 17 | needRoll = os.path.isfile(LOG_FILENAME) 18 | 19 | # Add the log message handler to the logger 20 | handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, backupCount=50) 21 | 22 | my_logger.addHandler(handler) 23 | 24 | # This is a stale log, so roll it 25 | if needRoll: 26 | # Add timestamp 27 | my_logger.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime()) 28 | 29 | # Roll over on application start 30 | my_logger.handlers[0].doRollover() 31 | 32 | # Add timestamp 33 | my_logger.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime()) 34 | 35 | # Log some messages 36 | for i in xrange(20): 37 | my_logger.debug('i = %d' % i) 38 | 39 | # See what files are created 40 | logfiles = glob.glob('%s*' % LOG_FILENAME) 41 | 42 | -------------------------------------------------------------------------------- /pthread/pthread_arg_error.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | an unsafe way to pass thread arguments. 3 | In this case, the argument var is changed by the main thread as it creates new threads 4 | ***************************************************************************************/ 5 | #include 6 | #include 7 | #include 8 | 9 | #define NUM_THREADS 8 10 | char *message[NUM_THREADS]; 11 | 12 | void *PrintHello(void *threadid) 13 | { 14 | int taskid; 15 | 16 | sleep(1); 17 | taskid = (int)threadid; 18 | printf("Thread %d\n", taskid); 19 | pthread_exit(NULL); 20 | } 21 | 22 | int main(int argc, char **argv) 23 | { 24 | pthread_t threads[NUM_THREADS]; 25 | int rc, t; 26 | 27 | for (t=0; t 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char **argv) 13 | { 14 | int data_processed = 0; 15 | int fileds[2] = {}; 16 | const char data[] = "Hello pipe"; 17 | char buffer[BUFSIZ + 1] = {}; 18 | pid_t pid; 19 | 20 | if (pipe(fileds) == 0) 21 | { 22 | pid = fork(); 23 | switch (pid) 24 | { 25 | case -1: 26 | fprintf(stderr, "Fork failure"); 27 | exit(EXIT_FAILURE); 28 | case 0: 29 | close(fileds[1]); 30 | data_processed = read(fileds[0], buffer, BUFSIZ); 31 | printf("read %d bytes: %s\n", data_processed, buffer); 32 | exit(EXIT_SUCCESS); 33 | default: 34 | close(fileds[0]); 35 | data_processed = write(fileds[1], data, strlen(data)); 36 | printf("wrote %d bytes: %s\n", data_processed, data); 37 | sleep(2); 38 | exit(EXIT_SUCCESS); 39 | } 40 | } 41 | 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /utility/msg_recv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct msg_st 9 | { 10 | long int msg_type; 11 | char text[BUFSIZ]; 12 | }; 13 | 14 | int main() 15 | { 16 | int running = 1; 17 | int msgid = -1; 18 | struct msg_st data = {}; 19 | long int msgtype = 0; 20 | 21 | //建立消息队列 22 | msgid = msgget((key_t)1234, 0666|IPC_CREAT); 23 | if (msgid == -1) 24 | { 25 | fprintf(stderr, "msgget failed with error: %d\n", errno); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | //从队列中获取消息,直到遇到end消息为止 30 | while (running) 31 | { 32 | if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1) 33 | { 34 | fprintf(stderr, "msgrcv failed with errno: %d\n", errno); 35 | exit(EXIT_FAILURE); 36 | } 37 | printf("read msg: %s\n", data.text); 38 | 39 | //遇到end结束 40 | if (strncmp(data.text, "end", 3) == 0) 41 | { 42 | running = 0; 43 | } 44 | } 45 | 46 | //删除消息队列 47 | if (msgctl(msgid, IPC_RMID, 0) == -1) 48 | { 49 | fprintf(stderr, "msgctl(IPC_RMID) failed\n"); 50 | exit(EXIT_FAILURE); 51 | } 52 | exit(EXIT_SUCCESS); 53 | } 54 | -------------------------------------------------------------------------------- /pthread/pthread_dotprod_serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | this is a simple serial program which computes the dot product of two vectors. The threaded version is pthread_dotprod_mutex.c 3 | * */ 4 | 5 | #include 6 | #include 7 | 8 | typedef struct { 9 | double *a; 10 | double *b; 11 | double sum; 12 | int veclen; 13 | } DOTDATA; 14 | 15 | #define VECLEN 100000 16 | DOTDATA dotstr; 17 | 18 | void dotprod() 19 | { 20 | int start, end, i; 21 | double mysum, *x, *y; 22 | 23 | start = 0; 24 | end = dotstr.veclen; 25 | x = dotstr.a; 26 | y = dotstr.b; 27 | 28 | mysum = 0; 29 | for (i=start; i 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len); 12 | pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len); 13 | 14 | #define read_lock(fd, offset, whence, len) \ 15 | lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len) 16 | 17 | #define readw_lock(fd, offset, whence, len) \ 18 | lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len) 19 | 20 | #define write_lock(fd, offset, whence, len) \ 21 | lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len) 22 | 23 | #define writew_lock(fd, offset, whence, len) \ 24 | lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len) 25 | 26 | #define un_lock(fd, offset, whence, len) \ 27 | lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len) 28 | 29 | #define is_read_lockable(fd, offset, whence, len) \ 30 | !lock_test(fd, F_RDLCK, offset, whence, len) 31 | 32 | #define is_write_lockable(fd, offset, whence, len) \ 33 | !lock_test(fd, F_WRLCK, offset, whence, len) 34 | 35 | #define my_lock(fd) (writew_lock(fd, 0, SEEK_SET, 0)) 36 | #define my_unlock(fd) (un_lock(fd, 0, SEEK_SET, 0)) 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /py/log_advanced/README.md: -------------------------------------------------------------------------------- 1 | ###Configuring Logging 2 | 3 | Programmers can configure logging in 3 ways: 4 | 5 | 1. Creating loggers, handlers, and formatters explicitly using Python code 6 | that calls the configuration methods 7 | 2. Creating a logging config file and reading it using `fileConfig()` function 8 | 3. Creating a dictionary of configuration information and passing it to the 9 | `dictConfig()` function 10 | 11 | Formatter 常用信息 12 | 13 | |formatter| 描述| 14 | |:--------------------|:-------------------------------------| 15 | |%(name)s | Logger的名字| 16 | |%(levelno)s | 数字形式的日志级别| 17 | |%(levelname)s | 文本形式的日志级别| 18 | |%(pathname)s | 调用日志输出函数的模块的完整路径名,可能没有| 19 | |%(filename)s | 调用日志输出函数的模块的文件名| 20 | |%(module)s | 调用日志输出函数的模块名| 21 | |%(funcName)s | 调用日志输出函数的函数名| 22 | |%(lineno)d | 调用日志输出函数的语句所在的代码行| 23 | |%(created)f | 当前时间,用UNIX标准的表示时间的浮 点数表示| 24 | |%(relativeCreated)d | 输出日志信息时的,自Logger创建以 来的毫秒数| 25 | |%(asctime)s | 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒| 26 | |%(thread)d | 线程ID。可能没有| 27 | |%(threadName)s | 线程名。可能没有| 28 | |%(process)d | 进程ID。可能没有| 29 | |%(message)s | 用户输出的消息| 30 | 31 | examples: 32 | 33 | - [x] config logger by calling API in code 34 | - [x] config with a dict in file 35 | - [x] config with a traditional config file 36 | - [x] logger can rotate according to size 37 | - [x] logger can rotate according to time 38 | - [x] logger rotate on restart 39 | -------------------------------------------------------------------------------- /py/log_advanced/logging_config_with_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import logging 5 | import logging.config 6 | 7 | ''' 8 | logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True) 9 | reads the logging configuration from a configparser-format file named fname. The 10 | format of the file should be as described in Configuration file format. This 11 | function can be called several times from an application, allowing an end user 12 | to select from various pre-canned configurations 13 | 14 | parameters: 15 | 1. defaults – Defaults to be passed to the ConfigParser can be specified in this argument. 16 | 2. disable_existing_loggers – If specified as False, loggers which exist when 17 | this call is made are left enabled. The default is True because this enables 18 | old behaviour in a backward- compatible way. This behaviour is to disable 19 | any existing loggers unless they or their ancestors are explicitly named in 20 | the logging configuration. 21 | ''' 22 | 23 | logging.config.fileConfig("logging.conf") 24 | 25 | # create logger 26 | logger = logging.getLogger("config_with_file") 27 | 28 | 29 | # 'application' code 30 | logger.debug("debug message") 31 | logger.info("info message") 32 | logger.warn("warn message") 33 | logger.error("error message") 34 | logger.critical("critical message") 35 | -------------------------------------------------------------------------------- /thrift/01/client.cpp: -------------------------------------------------------------------------------- 1 | #include "Serv.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace apache::thrift; 7 | using namespace apache::thrift::protocol; 8 | using namespace apache::thrift::transport; 9 | 10 | using boost::shared_ptr; 11 | 12 | int main(int argc, char **argv) { 13 | boost::shared_ptr socket(new TSocket("localhost", 9090)); 14 | #ifdef SIMPLE_SERVER 15 | boost::shared_ptr transport(new TBufferedTransport(socket)); 16 | #elif defined NONBLOCK_SERVER 17 | boost::shared_ptr transport(new TFramedTransport(socket)); 18 | #endif 19 | boost::shared_ptr protocol(new TBinaryProtocol(transport)); 20 | 21 | // 定义一个对象client,以"Serv"开头的类 22 | ServClient client(protocol); 23 | 24 | #ifdef NONBLOCK_SERVER 25 | socket->setConnTimeout(2000); 26 | socket->setRecvTimeout(2000); 27 | socket->setSendTimeout(2000); 28 | #endif 29 | 30 | transport->open(); 31 | 32 | // 先创建一个Student类型的变量,Student是我们在student.thrift中定义过的 33 | Student s; 34 | s.sno = 123; 35 | s.sname = "xiaoshe"; 36 | s.ssex = 1; 37 | s.sage = 30; 38 | 39 | 40 | // 最后调用put函数向服务端传输数据, put是student.thrift采用service定义的成员函数。 41 | // 调用put后,服务端也调用相应的put() 42 | client.put(s); 43 | 44 | transport->close(); 45 | 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /utility/back_trace01.c: -------------------------------------------------------------------------------- 1 | /* 2 | this example illustrates how to print out the backtrace of calling-functions. 3 | For systems using the GNU linker, it it necessary to use the -rdynamic linker option. 4 | Note, "static" function will not be exposed, and won't be available in the backtrace 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void myfunc3(void) 12 | { 13 | int j, nptrs; 14 | #define SIZE 100 15 | void *buffer[SIZE]; 16 | char **strings; 17 | 18 | nptrs = backtrace(buffer, SIZE); 19 | printf("backtrace() returned %d addresses\n", nptrs); 20 | 21 | strings = backtrace_symbols(buffer, nptrs); 22 | if (NULL == strings) { 23 | perror("backtrace_symbols"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | for (j=0; j 2 | #include 3 | #include 4 | 5 | #define NUM_THREADS 8 6 | char *message[NUM_THREADS]; 7 | 8 | void *PrintHello(void *threadid) 9 | { 10 | int *id_ptr, taskid; 11 | 12 | sleep(1); 13 | id_ptr = (int *)threadid; 14 | taskid = *id_ptr; 15 | printf("Thread %d: %s\n", taskid, message[taskid]); 16 | pthread_exit(NULL); 17 | } 18 | 19 | int main(int argc, char **argv) 20 | { 21 | pthread_t threads[NUM_THREADS]; 22 | int *taskids[NUM_THREADS]; 23 | int rc, t; 24 | 25 | message[0] = "English: Hello World!"; 26 | message[1] = "French: Bonjour, le monde!"; 27 | message[2] = "Spanish: Hola al mundo"; 28 | message[3] = "Klingon: Nuq neH!"; 29 | message[4] = "German: Guten Tag, Welt!"; 30 | message[5] = "Russian: Zdravstvytye, mir!"; 31 | message[6] = "Japan: Sekai e konnichiwa!"; 32 | message[7] = "Latin: Orbis, te saluto!"; 33 | 34 | for (t=0; t 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | 与命名管道相比,消息队列的优势: 10 | 1. 消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难 11 | 2. 通过发送消息可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法 12 | 3. 接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默默地接收。 13 | */ 14 | 15 | #define MAX_TEXT 512 16 | struct msg_st 17 | { 18 | long int msg_type; 19 | char text[MAX_TEXT]; 20 | }; 21 | 22 | int main() 23 | { 24 | int running = 1; 25 | struct msg_st data = {}; 26 | char buffer[BUFSIZ] = {}; 27 | int msgid = -1; 28 | 29 | //建立消息队列 30 | msgid = msgget((key_t)1234, 0666|IPC_CREAT); 31 | if (msgid == -1) 32 | { 33 | fprintf(stderr, "msgget failed with error: %d\n", errno); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | //向消息队列中写消息,直到写入end 38 | while (running) 39 | { 40 | //输入数据 41 | printf("enter some text: "); 42 | fgets(buffer, BUFSIZ, stdin); 43 | data.msg_type = 1; 44 | strcpy(data.text, buffer); 45 | 46 | //向队列中发送数据 47 | if (msgsnd(msgid, (void *)&data, MAX_TEXT, 0) == -1) 48 | { 49 | fprintf(stderr, "msgsnd failed\n"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | //输入end结束输入 54 | if (strncmp(buffer, "end", 3) == 0) 55 | { 56 | running = 0; 57 | } 58 | sleep(1); 59 | } 60 | 61 | exit(EXIT_SUCCESS); 62 | } 63 | -------------------------------------------------------------------------------- /network/sockserver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int server_sockfd = -1; 12 | int client_sockfd = -1; 13 | int client_len = 0; 14 | struct sockaddr_in server_addr = {}; 15 | struct sockaddr_in client_addr = {}; 16 | 17 | //创建流套接字 18 | server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 19 | 20 | //设置服务器接收的连接地址和监听的端口 21 | server_addr.sin_family = AF_INET; 22 | server_addr.sin_addr.s_addr = htons(INADDR_ANY); 23 | server_addr.sin_port = htons(9736); 24 | 25 | //绑定套接字 26 | bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); 27 | 28 | //创建套接字队列,监听套接字 29 | listen(server_sockfd, 5); 30 | 31 | //忽略子进程停止或退出信号 32 | signal(SIGCHLD, SIG_IGN); 33 | 34 | while (1) 35 | { 36 | char ch = 0; 37 | client_len = sizeof(client_addr); 38 | printf("server waiting\n"); 39 | client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_len); 40 | 41 | if (fork() == 0) 42 | { 43 | //子进程中,读取客户端发过来的信息,处理信息,再发送给客户端 44 | read(client_sockfd, &ch, 1); 45 | sleep(5); 46 | ch++; 47 | write(client_sockfd, &ch, 1); 48 | close(client_sockfd); 49 | exit(0); 50 | } 51 | else 52 | { 53 | close(client_sockfd); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /network/sockserver2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int server_sockfd = -1; 12 | int server_len = 0; 13 | int client_len = 0; 14 | char buffer[512] = {}; 15 | int result = 0; 16 | struct sockaddr_in server_addr = {}; 17 | struct sockaddr_in client_addr = {}; 18 | 19 | //创建数据报套接字 20 | server_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 21 | 22 | //设置监听IP端口 23 | server_addr.sin_family = AF_INET; 24 | server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 25 | server_addr.sin_port = htons(9739); 26 | server_len = sizeof(server_addr); 27 | 28 | //绑定套接字 29 | bind(server_sockfd, (struct sockaddr *)&server_addr, server_len); 30 | 31 | //忽略子进程停止或推出信号 32 | signal(SIGCHLD, SIG_IGN); 33 | 34 | while (1) 35 | { 36 | //接收数据,用client_addr来储存数据来源程序的IP端口 37 | result = recvfrom(server_sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_len); 38 | 39 | if (fork() == 0) 40 | { 41 | //利用子进程来处理数据 42 | buffer[0] += 'a' - 'A'; 43 | sleep(5); 44 | 45 | //发送处理后的数据 46 | sendto(server_sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, client_len); 47 | printf("%c\n", buffer[0]); 48 | //注意一定要关闭子进程,要不然程序运行会异常 49 | exit(0); 50 | } 51 | } 52 | 53 | close(server_sockfd); 54 | } 55 | -------------------------------------------------------------------------------- /ipc/mmap/count01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../unpipc.h" 10 | 11 | 12 | #define SEM_NAME "mysem" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | int fd, i, nloop, zero = 0; 17 | int *ptr = NULL; 18 | sem_t *mutex; 19 | 20 | if (3 != argc) 21 | { 22 | fprintf(stderr, "usage: %s <#loops>\n", argv[0]); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | nloop = atoi(argv[2]); 27 | 28 | // open file, initialize to 0, map into memory 29 | fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE); 30 | write(fd, &zero, sizeof(int)); 31 | 32 | // 1. mmap 2. fork 33 | ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 34 | close(fd); 35 | 36 | // create, initialize and unlink semaphore 37 | mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1); 38 | sem_unlink(SEM_NAME); 39 | 40 | setbuf(stdout, NULL); // stdout is unbuffered 41 | if (0 == fork()) 42 | { 43 | for (i = 0; i < nloop; ++i) 44 | { 45 | sem_wait(mutex); 46 | // 这里直接操作内存, 不再需要read, write这些操作 47 | printf("child: %d\n", (*ptr)++); 48 | sem_post(mutex); 49 | } 50 | exit(EXIT_SUCCESS); 51 | } 52 | 53 | for (i = 0; i < nloop; ++i) 54 | { 55 | sem_wait(mutex); 56 | printf("parent: %d\n", (*ptr)++); 57 | sem_post(mutex); 58 | } 59 | exit(EXIT_SUCCESS); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /ipc/mmap/count02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../unpipc.h" 10 | 11 | 12 | struct shared 13 | { 14 | sem_t mutex; // the mutex: a Posix memory-based semaphore 15 | int count; 16 | } shared; 17 | 18 | int main(int argc, char **argv) 19 | { 20 | int fd, i, nloop; 21 | struct shared *ptr; 22 | 23 | if (3 != argc) 24 | { 25 | fprintf(stderr, "usage: %s <#loops>\n", argv[0]); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | nloop = atoi(argv[2]); 30 | 31 | // open file, initialize to 0, map into memory 32 | fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE); 33 | write(fd, &shared, sizeof(struct shared)); 34 | 35 | // 1. mmap 2. fork 36 | ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 37 | close(fd); 38 | 39 | // initialize semaphore that is shared between processes 40 | sem_init(&ptr->mutex, 1, 1); 41 | 42 | setbuf(stdout, NULL); 43 | if (0 == fork()) 44 | { 45 | for (i = 0; i < nloop; ++i) 46 | { 47 | sem_wait(&ptr->mutex); 48 | // 这里直接操作内存, 不再需要read, write这些操作 49 | printf("child: %d\n", ptr->count++); 50 | sem_post(&ptr->mutex); 51 | } 52 | exit(EXIT_SUCCESS); 53 | } 54 | 55 | for (i = 0; i < nloop; ++i) 56 | { 57 | sem_wait(&ptr->mutex); 58 | printf("parent: %d\n", ptr->count++); 59 | sem_post(&ptr->mutex); 60 | } 61 | exit(EXIT_SUCCESS); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /utility/shmread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "shmdata.h" 6 | 7 | int main() 8 | { 9 | int running = 1; //程序是否继续运行的标志 10 | void *shm = NULL; //分配的共享内存的原始首地址 11 | struct shared_use_st *shared = NULL; //指向shm 12 | int shmid; //共享内存标识符 13 | 14 | //创建共享内存 15 | shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); 16 | if (shmid == -1) 17 | { 18 | fprintf(stderr, "shmget failed\n"); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | //将共享内存连接到当前进程的地址空间 23 | shm = shmat(shmid, 0, 0); 24 | if (shm == (void *)-1) 25 | { 26 | fprintf(stderr, "shmat failed\n"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | printf("\n%d memory attached at %X\n", getpid(), (int)shm); 31 | 32 | //设置共享内存 33 | shared = (struct shared_use_st *)shm; 34 | shared->written = 0; 35 | while (running) //读取共享内存中的数据 36 | { 37 | //没有进程向共享内存写数据,有数据可读取 38 | if (shared->written != 0) 39 | { 40 | printf("read text: %s", shared->text); 41 | //读取完数据,设置written使共享内存段可写 42 | shared->written = 0; 43 | sleep(2); 44 | //输入了end,退出循环 45 | if (strncmp(shared->text, "end", 3) == 0) 46 | { 47 | running = 0; 48 | } 49 | } 50 | else //有其他进程在写数据,不能读取数据 51 | { 52 | sleep(1); 53 | } 54 | } 55 | 56 | //删除共享内存 57 | if (shmctl(shmid, IPC_RMID, 0) == -1) 58 | { 59 | fprintf(stderr, "shmctl(IPC_RMID) failed\n"); 60 | exit(EXIT_FAILURE); 61 | } 62 | exit(EXIT_SUCCESS); 63 | } 64 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_recv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int main(int argc, char **argv) 11 | { 12 | int c, flags, ret; 13 | mqd_t mqd; 14 | ssize_t n; 15 | unsigned int prio; 16 | void *buff = NULL; 17 | struct mq_attr attr = {}; 18 | 19 | flags = O_RDONLY; 20 | while ((c = getopt(argc, argv, "n")) != -1) 21 | { 22 | switch (c) 23 | { 24 | case 'n': 25 | flags |= O_NONBLOCK; 26 | break; 27 | } 28 | } 29 | 30 | if (optind != argc-1) 31 | { 32 | fprintf(stderr, "usage: mq_recv [-n] \n"); 33 | exit(-1); 34 | } 35 | 36 | mqd = mq_open(argv[optind], flags); 37 | if (-1 == mqd) 38 | { 39 | fprintf(stdout, "mq_open error:%d\n", errno); 40 | } 41 | 42 | // 这里是要获取attr中的属性msgsize,来确定mq_receive需要开辟的buff大小 43 | ret = mq_getattr(mqd, &attr); 44 | if (-1 == ret) 45 | { 46 | fprintf(stderr, "mq_getattr error:%d\n", errno); 47 | exit(-1); 48 | } 49 | fprintf(stdout, "max #msgs=%ld, max #bytes/msg=%ld, #currently on queue = %ld\n", 50 | attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs); 51 | 52 | buff = malloc(attr.mq_msgsize); //buff的空间要不小于attr的msgsize成员,否则mq_receive会返回EMSGSIZE错误 53 | 54 | // mq_receive总是返回最高优先级的最早消息 55 | n = mq_receive(mqd, buff, attr.mq_msgsize, &prio); 56 | if (-1 == n) 57 | { 58 | fprintf(stderr, "mq_receive error:%d\n", errno); 59 | exit(-1); 60 | } 61 | 62 | printf("read %ld bytes, priority = %u\n", (long)n, prio); //数值越大,优先级越高 63 | 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_create.c: -------------------------------------------------------------------------------- 1 | /* 2 | 创建一个msg_queue 3 | 编译需要链接 -lrt 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../unpipc.h" 13 | 14 | int main(int argc, char **argv) 15 | { 16 | int flags = O_RDWR | O_CREAT | O_EXCL; 17 | mqd_t mqd; 18 | int c = 0; 19 | struct mq_attr attr = {}; 20 | 21 | while ((c = getopt(argc, argv, "em:z:") != -1)) 22 | { 23 | switch (c) 24 | { 25 | case 'e': 26 | flags |= O_EXCL; 27 | break; 28 | case 'm': 29 | attr.mq_maxmsg = atol(optarg); 30 | break; 31 | case 'z': 32 | attr.mq_msgsize = atol(optarg); 33 | break; 34 | } 35 | } 36 | 37 | if (optind != argc-1) 38 | { 39 | fprintf(stderr, "usage: mq_create [-e] [-m maxmsg -z msgsize] \n"); 40 | exit(-1); 41 | } 42 | 43 | // mq_msgsize and mq_maxmsg must be set at the same time 44 | if ((attr.mq_maxmsg == 0 && attr.mq_msgsize != 0) || (attr.mq_maxmsg != 0 && attr.mq_msgsize == 0)) 45 | { 46 | fprintf(stderr, "must specify both -m maxmsg and -z msgsize at the same time"); 47 | exit(-1); 48 | } 49 | 50 | mqd = mq_open(argv[optind], flags, FILE_MODE, (attr.mq_maxmsg != 0) ? &attr: NULL); 51 | if (-1 == mqd) 52 | { 53 | fprintf(stderr, "mq_open %s error:%d\n", argv[1], errno); 54 | exit(-1); 55 | } 56 | 57 | // mq_close后, 调用进程可不再使用该描述符,但其消息队列并不从系统中删除 58 | // 一个进程终止时,它的所有打开着的消息队列都关闭,就像调用了mq_close一样 59 | // 要从系统中删除用作mq_open第一个参数的某个name, 必须调用mq_unlink 60 | mq_close(mqd); 61 | 62 | return 0; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /ipc/pipe/fifo_read.c: -------------------------------------------------------------------------------- 1 | // 从FIFO中读取数据,写入到文件datafromfifo.txt中 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../unpipc.h" 13 | 14 | 15 | int main() 16 | { 17 | int read_fd = -1; 18 | int write_fd = -1; 19 | int res = 0; 20 | char buffer[PIPE_BUF+1] = {}; 21 | int bytes_read = 0; 22 | int bytes_write = 0; 23 | 24 | res = mkfifo(FIFO, FILE_MODE); 25 | if (res < 0 && errno != EEXIST) 26 | { 27 | fprintf(stderr, "mkfifo error: %d, %s\n", errno, FIFO); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | printf("process %d opening fifo o_rdonly\n", getpid()); 32 | 33 | read_fd = open(FIFO, O_RDONLY); 34 | write_fd = open("datafromfifo.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644); 35 | printf("process %d result: readfd=%d, writefd=%d\n", getpid(), read_fd, write_fd); 36 | 37 | if (read_fd != -1) 38 | { 39 | do 40 | { 41 | memset(buffer, 0, sizeof(buffer)); 42 | res = read(read_fd, buffer, PIPE_BUF); 43 | printf("read from FIFO %s: [%d]%s\n", FIFO, res, buffer); 44 | if (res > 0) 45 | { 46 | bytes_write = write(write_fd, buffer, res); 47 | bytes_read += res; 48 | } 49 | } while (res > 0); 50 | close(read_fd); 51 | close(write_fd); 52 | } 53 | else 54 | { 55 | fprintf(stderr, "read_fd == -1\n"); 56 | exit(EXIT_FAILURE); 57 | } 58 | 59 | unlink(FIFO); 60 | printf("process %d finished, %d bytes read\n", getpid(), bytes_read); 61 | exit(EXIT_SUCCESS); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /pthread/pthread_stack.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | 3 | ****************************************************************************************************/ 4 | #include 5 | #include 6 | #include 7 | 8 | #define NTHREADS 4 9 | #define N 1000 10 | #define MEGEXTRA 1000000 11 | 12 | pthread_attr_t attr; 13 | 14 | void *dowork(void *threadid) 15 | { 16 | double A[N][N]; 17 | int i, j; 18 | long tid; 19 | size_t mystacksize; 20 | 21 | tid = (long)threadid; 22 | pthread_attr_getstacksize(&attr, &mystacksize); 23 | printf("Thread %ld: stack size = %zi bytes \n", tid, mystacksize); 24 | 25 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "shmdata.h" 7 | 8 | /* 9 | *使用共享内存的优点: 10 | * 进程间通信非常方便,接口简单,数据的共享使得进程间数据不需要传送,而是直接访问内存,加快程序效率, 11 | * 也不像匿名管道那样要求进程有一定的父子关系 12 | *缺点: 13 | * 共享内存没有提供同步的机制,使得我们在使用共享内存进行进程间通信时,要借助于其他的手段来进行进程间的同步工作 14 | */ 15 | 16 | int main() 17 | { 18 | int running = 1; 19 | void *shm = NULL; 20 | struct shared_use_st *shared = NULL; 21 | char buffer[BUFSIZ+1] = {};//用于保存输入的文本 22 | int shmid; 23 | 24 | //创建共享内存 25 | shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); 26 | if (shmid == -1) 27 | { 28 | fprintf(stderr, "shmget failed\n"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | //将共享内存连接到当前进程的地址空间 33 | shm = shmat(shmid, (void *)0, 0); 34 | if (shm == (void *)-1) 35 | { 36 | fprintf(stderr, "shmat failed\n"); 37 | exit(EXIT_FAILURE); 38 | } 39 | printf("\n%d memory attached at %X\n", getpid(), (int)shm); 40 | 41 | //设置共享内存 42 | shared = (struct shared_use_st *)shm; 43 | while (running) //向共享内存写数据 44 | { 45 | //数据还没被读取,则等待数据被读取,不能向共享内存写入文本 46 | while (shared->written == 1) 47 | { 48 | sleep(1); 49 | printf("waiting ... \n"); 50 | } 51 | 52 | //向共享内存写入数据 53 | printf("enter some text: "); 54 | fgets(buffer, BUFSIZ, stdin); 55 | strncpy(shared->text, buffer, TEXT_SZ); 56 | //写完数据,设置written是共享内存段可读 57 | shared->written = 1; 58 | //输入了end, 退出循环 59 | if (strncmp(buffer, "end", 3) == 0) 60 | { 61 | running = 0; 62 | } 63 | } 64 | 65 | //把共享内存从当前进程中分离 66 | if (shmdt(shm) == -1) 67 | { 68 | fprintf(stderr, "shmdt failed\n"); 69 | exit(EXIT_FAILURE); 70 | } 71 | 72 | sleep(2); 73 | exit(EXIT_SUCCESS); 74 | } 75 | -------------------------------------------------------------------------------- /ipc/pipe/fifo_write.c: -------------------------------------------------------------------------------- 1 | // 从文件data.txt中读出数据,写入到FIFO中 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../unpipc.h" 13 | 14 | 15 | int main(int argc, char **argv) 16 | { 17 | int write_fd = -1; 18 | int read_fd = -1; 19 | int res = 0; 20 | int bytes_sent = 0; 21 | char buffer[PIPE_BUF+1] = {}; 22 | 23 | res = mkfifo(FIFO, FILE_MODE); 24 | if (res != 0 && EEXIST != errno) 25 | { 26 | fprintf(stderr, "could not create fifo %s\n", FIFO); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | printf("process %d opening fifo w_wronly\n", getpid()); 31 | 32 | write_fd = open(FIFO, O_WRONLY); 33 | read_fd = open("data.txt", O_RDONLY); 34 | printf("process %d result: writefd=%d, readfd=%d\n", getpid(), write_fd, read_fd); 35 | 36 | if (write_fd != -1) 37 | { 38 | int bytes_read = 0; 39 | bytes_read = read(read_fd, buffer, PIPE_BUF); 40 | printf("read from %s :%s\n", "data.txt", buffer); 41 | while (bytes_read > 0) 42 | { 43 | buffer[bytes_read] = 0; 44 | res = write(write_fd, buffer, bytes_read); 45 | if (res == -1) 46 | { 47 | fprintf(stderr, "write error on pipe\n"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | bytes_sent += res; 52 | memset(buffer, 0, sizeof(buffer)); 53 | bytes_read = read(read_fd, buffer, PIPE_BUF); 54 | printf("read from %s :[%d]%s\n", "data.txt", bytes_read, buffer); 55 | } 56 | close(write_fd); 57 | close(read_fd); 58 | } 59 | else 60 | { 61 | fprintf(stderr, "write_fd == -1\n"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | printf("process %d finished\n", getpid()); 66 | exit(EXIT_SUCCESS); 67 | } 68 | -------------------------------------------------------------------------------- /ipc/mmap/producer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "pro_con.h" 12 | #include "../unpipc.h" 13 | 14 | 15 | 16 | int main(int argc, char **argv) 17 | { 18 | int fd, i, nloop, nusec; 19 | pid_t pid; 20 | char mesg[MESGSIZE]; 21 | long offset; 22 | struct shmstruct *ptr = NULL; 23 | 24 | if (4 != argc) 25 | { 26 | fprintf(stderr, "usage: %s <#nloops> <#usec>\n", argv[0]); 27 | exit(EXIT_FAILURE); 28 | } 29 | nloop = atoi(argv[2]); 30 | nusec = atoi(argv[3]); 31 | 32 | // open and map shared memory that producer must create 33 | fd = shm_open(argv[1], O_RDWR, FILE_MODE); 34 | ptr = mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 35 | close(fd); 36 | 37 | pid = getpid(); 38 | for (i = 0; i < nloop; ++i) 39 | { 40 | usleep(nusec); 41 | snprintf(mesg, MESGSIZE, "pid %ld: msg: %d\n", (long)pid, i); 42 | 43 | if (sem_trywait(&ptr->nempty) == -1) 44 | { 45 | if (EAGAIN == errno) 46 | { 47 | sem_wait(&ptr->noverflowmutex); 48 | ptr->noverflow++; 49 | sem_post(&ptr->noverflowmutex); 50 | continue; 51 | } 52 | else 53 | { 54 | fprintf(stderr, "sem_trywait error\n"); 55 | exit(EXIT_FAILURE); 56 | } 57 | } 58 | sem_wait(&ptr->mutex); 59 | offset = ptr->msgoff[ptr->nput]; 60 | if (++(ptr->nput) >= NMESG) 61 | { 62 | ptr->nput = 0; // circulate buffer 63 | } 64 | sem_post(&ptr->mutex); 65 | strcpy(&ptr->msgdata[offset], mesg); 66 | sem_post(&ptr->nstored); 67 | } 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /utility/url_decode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | 7 | static int hexit( char c ) 8 | { 9 | if ( c >= '0' && c <= '9' ) 10 | return c - '0'; 11 | if ( c >= 'a' && c <= 'f' ) 12 | return c - 'a' + 10; 13 | if ( c >= 'A' && c <= 'F' ) 14 | return c - 'A' + 10; 15 | return 0; /* shouldn't happen, we're guarded by isxdigit() */ 16 | } 17 | 18 | 19 | 20 | static void strdecode( char* to, char* from ) 21 | { 22 | for ( ; *from != '\0'; ++to, ++from ) 23 | { 24 | if ( from[0] == '%' && isxdigit( from[1] ) && isxdigit( from[2] ) ) 25 | { 26 | *to = hexit( from[1] ) * 16 + hexit( from[2] ); 27 | from += 2; 28 | } 29 | else 30 | *to = *from; 31 | } 32 | *to = '\0'; 33 | } 34 | 35 | 36 | static void strencode( char* to, size_t tosize, const char* from ) 37 | { 38 | int tolen; 39 | 40 | for ( tolen = 0; *from != '\0' && tolen + 4 < tosize; ++from ) 41 | { 42 | if ( isalnum(*from) || strchr( "/_.-~", *from ) != (char*) 0 ) 43 | { 44 | *to = *from; 45 | ++to; 46 | ++tolen; 47 | } 48 | else 49 | { 50 | (void) sprintf( to, "%%%02x", (int) *from & 0xff ); 51 | to += 3; 52 | tolen += 3; 53 | } 54 | } 55 | *to = '\0'; 56 | } 57 | 58 | int main(int argc, char **argv) 59 | { 60 | char encoded_url[1024] = "http%3a%2f%2f192.168.109.247%2f%e7%a7%81%e4%ba%ba%e8%ae%a2%e5%88%b6.HD1280%e8%b6%85%e6%b8%85%e5%9b%bd%e8%af%ad%e4%b8%ad%e8%8b%b1%e5%8f%8c%e5%ad%97.mkv"; 61 | char decoded_url[1024] = {}; 62 | 63 | strdecode(decoded_url, encoded_url); 64 | printf("encoded_url:%s\ndecoded_url:%s\n", encoded_url, decoded_url); 65 | memset(encoded_url, 0, sizeof(encoded_url)); 66 | strencode(encoded_url, sizeof(encoded_url), decoded_url); 67 | printf("encoded_url:%s\n", encoded_url); 68 | 69 | 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /pthread/pthread_join.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************************** 2 | This example demonstrates how to "wait" for thread completion by using the Pthread join routine. 3 | Threads are explicitly created in a joinable state for portability reasons. 4 | *******************************************************************************************/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define NUM_THREADS 4 11 | 12 | void *BusyWork(void *t) 13 | { 14 | int i; 15 | long tid; 16 | double result = 0.0; 17 | tid = (long)t; 18 | 19 | printf("Thread %ld starting ...\n", tid); 20 | for (i=0; i<1000000; i++) { 21 | result += sin(i) * tan(i); 22 | } 23 | printf("Thread %ld done. Result = %e\n", tid, result); 24 | pthread_exit((void *)t); 25 | } 26 | 27 | 28 | int main(int argc, char **argv) 29 | { 30 | pthread_t thread[NUM_THREADS]; 31 | pthread_attr_t attr; 32 | int rc; 33 | long t; 34 | void *status; 35 | 36 | /* Initialize and set thread detached attribute */ 37 | pthread_attr_init(&attr); 38 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 39 | 40 | for (t=0; t 5 | #include 6 | #include 7 | 8 | #define NUM_THREADS 8 9 | char *message[NUM_THREADS]; 10 | 11 | struct thread_data { 12 | int thread_id; 13 | int sum; 14 | char *message; 15 | }; 16 | 17 | struct thread_data thread_data_array[NUM_THREADS]; 18 | 19 | void *PrintHello(void *threadarg) 20 | { 21 | int taskid, sum; 22 | char *hello_msg; 23 | struct thread_data *my_data; 24 | 25 | sleep(1); 26 | my_data = (struct thread_data *)threadarg; 27 | taskid = my_data->thread_id; 28 | sum = my_data->sum; 29 | hello_msg = my_data->message; 30 | 31 | printf("Thread %d: %s sum=%d\n", taskid, hello_msg, sum); 32 | pthread_exit(NULL); 33 | } 34 | 35 | int main(int argc, char **argv) 36 | { 37 | pthread_t threads[NUM_THREADS]; 38 | int *taskids[NUM_THREADS]; 39 | int rc, t, sum; 40 | 41 | sum = 0; 42 | message[0] = "English: Hello World!"; 43 | message[1] = "French: Bonjour, le monde!"; 44 | message[2] = "Spanish: Hola al mundo"; 45 | message[3] = "Klingon: Nuq neH!"; 46 | message[4] = "German: Guten Tag, Welt!"; 47 | message[5] = "Russian: Zdravstvytye, mir!"; 48 | message[6] = "Japan: Sekai e konnichiwa!"; 49 | message[7] = "Latin: Orbis, te saluto!"; 50 | 51 | for (t=0; t 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "pro_con.h" 12 | #include "../unpipc.h" 13 | 14 | 15 | 16 | int main(int argc, char **argv) 17 | { 18 | int fd, index, lastnoverflow, temp; 19 | long offset; 20 | struct shmstruct *ptr = NULL; 21 | 22 | if (2 != argc) 23 | { 24 | fprintf(stderr, "usage: %s \n", argv[0]); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | // create shm, set its size, map it, close descriptor 29 | shm_unlink(argv[1]); 30 | fd = shm_open(argv[1], O_RDWR | O_CREAT | O_EXCL, FILE_MODE); 31 | ptr = mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 32 | ftruncate(fd, sizeof(struct shmstruct)); 33 | close(fd); 34 | 35 | // initialize the array of offsets 36 | for (index = 0; index < NMESG; index++) 37 | { 38 | ptr->msgoff[index] = index * MESGSIZE; 39 | } 40 | 41 | // initialize the array of offsets 42 | sem_init(&ptr->mutex, 1, 1); 43 | sem_init(&ptr->nempty, 1, NMESG); 44 | sem_init(&ptr->nstored, 1, 0); 45 | sem_init(&ptr->noverflowmutex, 1, 1); 46 | 47 | index = 0; 48 | lastnoverflow = 0; 49 | for (;;) 50 | { 51 | sem_wait(&ptr->nstored); 52 | sem_wait(&ptr->mutex); 53 | offset = ptr->msgoff[index]; 54 | printf("index = %d: %s\n", index, &ptr->msgdata[offset]); 55 | if (++index >= NMESG) 56 | { 57 | index = 0; // circulate buffer 58 | } 59 | sem_post(&ptr->mutex); 60 | sem_post(&ptr->nempty); 61 | 62 | sem_wait(&ptr->noverflowmutex); 63 | temp = ptr->noverflow; 64 | sem_post(&ptr->noverflowmutex); 65 | if (temp != lastnoverflow) 66 | { 67 | printf("noverflow = %d\n", temp); 68 | lastnoverflow = temp; 69 | } 70 | } 71 | 72 | exit(EXIT_SUCCESS); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_notify04.c: -------------------------------------------------------------------------------- 1 | /* 2 | 使用线程来处理异步事件通知 3 | 把sigev_notify设置成SIGEV_THREAD 4 | 该线程调用由sigev_notify_function指定的函数,所用的参数由sigev_value指定,新线程的属性由sigev_notify_attributes 5 | 指定,NULL表示默认属性。 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | mqd_t mqd; 20 | struct mq_attr attr; 21 | struct sigevent sigev; 22 | 23 | static void notify_thread(union sigval); // our thread function 24 | 25 | int main(int argc, char **argv) 26 | { 27 | int ret = 0; 28 | 29 | if (argc != 2) 30 | { 31 | fprintf(stdout, "usage: mq_notify03 \n"); 32 | exit(-1); 33 | } 34 | 35 | mqd = mq_open(argv[1], O_RDONLY | O_NONBLOCK); 36 | if (-1 == mqd) 37 | { 38 | perror("mq_open error"); 39 | exit(-1); 40 | } 41 | ret = mq_getattr(mqd, &attr); 42 | if (-1 == ret) 43 | { 44 | perror("mq_getattr error"); 45 | exit(-1); 46 | } 47 | 48 | sigev.sigev_notify = SIGEV_THREAD; 49 | sigev.sigev_value.sival_ptr = NULL; 50 | sigev.sigev_notify_function = notify_thread; 51 | sigev.sigev_notify_attributes = NULL; 52 | 53 | ret = mq_notify(mqd, &sigev); 54 | if (-1 == ret) 55 | { 56 | perror("mq_notify err"); 57 | exit(-1); 58 | } 59 | 60 | for (;;) 61 | { 62 | pause(); 63 | } 64 | 65 | exit(0); 66 | } 67 | 68 | static void notify_thread(union sigval arg) 69 | { 70 | ssize_t n; 71 | void *buff = NULL; 72 | 73 | printf("notify_thread started\n"); 74 | buff = malloc(attr.mq_msgsize); 75 | assert(NULL != buff); 76 | 77 | while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) 78 | { 79 | printf("read %ld bytes\n", (long)n); 80 | } 81 | if (errno != EAGAIN) // 表示暂无消息可读,属于正常现象 82 | { 83 | perror("mq_receive error"); 84 | exit(-1); 85 | } 86 | 87 | free(buff);buff = NULL; 88 | pthread_exit(NULL); 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /ipc/rd_wr_lock/README.md: -------------------------------------------------------------------------------- 1 | ##读写锁 2 | === 3 | 4 | 读写锁是作为pthread_rwlock_t数据类型的变量在内存中分配的。 5 | 当读写锁是在单个进程内的各个线程间共享时,这些变量可以定义在那个进程内; 6 | 当读写锁是在共享某个内存区的进程间共享时,这些变量应该定义在该共享内存区中。 7 | 8 | ###读写锁的分配原则 9 | --- 10 | 11 | 1. 只要没有线程持有某个给定的读写锁用于写,那么任意数目的线程才可以持有该读写锁用于读 12 | 2. 仅当没有线程持有某个给定的读写锁用于读或写时,才能分配该读写锁用于写。 13 | 14 | 某些应用中读数据比修改数据频繁,这些应用可以从改用读写锁代替互斥锁中获益。 15 | 任意给定时刻允许多个读出者存在提供了更高的并发度,同时在某个写入者修改数 16 | 据期间保护该数据,以免任何其他读出者或写入者的干扰。 17 | 18 | 读写锁的一个日常类比是访问银行账户。 19 | 20 | ```cpp 21 | #include 22 | 23 | int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr); //获取一个读出锁 24 | int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr); //获取一个写入锁 25 | int pthread_rwlock_unlock(pthread_rwlock_t *rwptr); 26 | int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr); 27 | int pthread_rwlock_trywrlock(pthread_rwlock_t *rwptr); 28 | 返回: 成功返回0,失败返回Exxx错误码 29 | 30 | ``` 31 | 32 | ###读写锁属性 33 | --- 34 | 35 | 1. 静态分配的读写锁,可以用常值PTHREAD_RWLOCK_INITIALIZER来初始化 36 | 2. 调用pthread_rwlock_init来动态初始化 37 | 3. 当一个线程不再需要某个读写锁时,可以调用pthread_rwlock_destroy来销毁它 38 | 39 | ```cpp 40 | #include 41 | 42 | int pthread_rwlock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr); 43 | int pthread_rwlock_destroy(pthread_rwlock_t *rwptr); 44 | 返回: 成功返回0,失败返回Exxx错误码 45 | 46 | ``` 47 | 48 | 数据类型为pthread_rwlockattr_t的某个属性对象一旦初始化,可以通过调用不同的函数来启用 49 | 或禁止特定属性。当前定义了的唯一属性是PTHREAD_PROCESS_SHARED。 50 | 51 | ```cpp 52 | #include 53 | 54 | int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *valptr); 55 | int pthread_rwlockattr_setpshared(const pthread_rwlockattr_t *attr, int value); 56 | 返回: 成功返回0,失败返回Exxx错误码 57 | 58 | ``` 59 | 60 | value的值可以为PTHREAD_PROCESS_PRIVATE或PTHREAD_PROCESS_SHARED 61 | 62 | ###线程清理处理程序 63 | --- 64 | 65 | 有时候,线程会在持有锁期间被动(被其他线程cancel)或主动终止(主动调用pthread_exit)。 66 | 为了处理这种情况,线程可以安装或删除清理处理程序 67 | 68 | ```cpp 69 | #include 70 | 71 | void pthread_cleanup_push(void (*function)(void *), void *arg); 72 | 73 | // 删除调用线程的取消清理栈中位于栈顶的函数。如果excute不为0,就调用该函数 74 | void pthread_cleanup_pop(int execute); 75 | 返回: 成功返回0,失败返回Exxx错误码 76 | 77 | ``` 78 | 79 | ###小结 80 | --- 81 | 82 | 与普通的互斥锁相比,当被保护数据的读访问比写访问更为频繁时,读写锁能够提供更高的并发度。 83 | 84 | 85 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/student_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.1) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef student_TYPES_H 8 | #define student_TYPES_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | 18 | 19 | 20 | typedef struct _Student__isset { 21 | _Student__isset() : sno(false), sname(false), ssex(false), sage(false) {} 22 | bool sno; 23 | bool sname; 24 | bool ssex; 25 | bool sage; 26 | } _Student__isset; 27 | 28 | class Student { 29 | public: 30 | 31 | static const char* ascii_fingerprint; // = "457B6E35E5EAAA1DBF18D6B3763BD82E"; 32 | static const uint8_t binary_fingerprint[16]; // = {0x45,0x7B,0x6E,0x35,0xE5,0xEA,0xAA,0x1D,0xBF,0x18,0xD6,0xB3,0x76,0x3B,0xD8,0x2E}; 33 | 34 | Student() : sno(0), sname(), ssex(0), sage(0) { 35 | } 36 | 37 | virtual ~Student() throw() {} 38 | 39 | int32_t sno; 40 | std::string sname; 41 | bool ssex; 42 | int16_t sage; 43 | 44 | _Student__isset __isset; 45 | 46 | void __set_sno(const int32_t val) { 47 | sno = val; 48 | } 49 | 50 | void __set_sname(const std::string& val) { 51 | sname = val; 52 | } 53 | 54 | void __set_ssex(const bool val) { 55 | ssex = val; 56 | } 57 | 58 | void __set_sage(const int16_t val) { 59 | sage = val; 60 | } 61 | 62 | bool operator == (const Student & rhs) const 63 | { 64 | if (!(sno == rhs.sno)) 65 | return false; 66 | if (!(sname == rhs.sname)) 67 | return false; 68 | if (!(ssex == rhs.ssex)) 69 | return false; 70 | if (!(sage == rhs.sage)) 71 | return false; 72 | return true; 73 | } 74 | bool operator != (const Student &rhs) const { 75 | return !(*this == rhs); 76 | } 77 | 78 | bool operator < (const Student & ) const; 79 | 80 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 81 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 82 | 83 | }; 84 | 85 | void swap(Student &a, Student &b); 86 | 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /protobuf/reader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "addressbook.pb.h" 5 | 6 | 7 | using namespace std; 8 | 9 | void list_people(const AddressBook &address_book) 10 | { 11 | for (int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int pipefd[2]; 15 | static void sig_usr1(int); 16 | 17 | int main(int argc, char **argv) 18 | { 19 | int nfds = 0; 20 | char c; 21 | fd_set rset; 22 | mqd_t mqd; 23 | void *buff = NULL; 24 | ssize_t n; 25 | struct mq_attr attr; 26 | struct sigevent sigev; 27 | int ret = 0; 28 | 29 | if (2 != argc) 30 | { 31 | fprintf(stderr, "usage: %s \n", argv[0]); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | mqd = mq_open(argv[1], O_RDONLY | O_NONBLOCK); 36 | if (-1 == mqd) 37 | { 38 | perror("mq_open error"); 39 | exit(-1); 40 | } 41 | ret = mq_getattr(mqd, &attr); 42 | if (-1 == ret) 43 | { 44 | perror("mq_getattr error"); 45 | exit(-1); 46 | } 47 | buff = malloc(attr.mq_msgsize); //buff的空间要不小于attr的msgsize成员,否则mq_receive会返回EMSGSIZE错误 48 | assert(buff); 49 | 50 | signal(SIGUSR1, sig_usr1); 51 | sigev.sigev_notify= SIGEV_SIGNAL; 52 | sigev.sigev_signo = SIGUSR1; 53 | ret = mq_notify(mqd, &sigev); 54 | if (-1 == ret) 55 | { 56 | perror("mq_notify err"); 57 | exit(-1); 58 | } 59 | 60 | FD_ZERO(&rset); 61 | for(;;) 62 | { 63 | FD_SET(pipefd[0], &rset); 64 | nfds = select(pipefd[0]+1, &rset, NULL, NULL, NULL); 65 | 66 | if (FD_ISSET(pipefd[0], &rset)) 67 | { 68 | read(pipefd[0], &c, 1); 69 | mq_notify(mqd, &sigev); 70 | while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) 71 | { 72 | printf("read %ld bytes\n", (long)n); 73 | } 74 | if (errno != EAGAIN) // 表示暂无消息可读,属于正常现象 75 | { 76 | perror("mq_receive error"); 77 | exit(-1); 78 | } 79 | } 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | static void sig_usr1(int signo) 86 | { 87 | write(pipefd[1], "", 1); 88 | return; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_notify01.c: -------------------------------------------------------------------------------- 1 | /* 2 | Posix消息队列允许异步事件通知,以告知何时有一个消息放置到了某个空消息队列中 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | volatile sig_atomic_t mqflag; // set nonzero by signal handler 15 | static void sig_usr1(int); 16 | 17 | int main(int argc, char **argv) 18 | { 19 | mqd_t mqd; 20 | void *buff = NULL; 21 | ssize_t n; 22 | sigset_t zeromask, newmask, oldmask; 23 | struct mq_attr attr; 24 | struct sigevent sigev; 25 | int ret = 0; 26 | 27 | if (argc != 2) 28 | { 29 | fprintf(stdout, "usage: mq_notify02 \n"); 30 | exit(-1); 31 | } 32 | 33 | mqd = mq_open(argv[1], O_RDONLY | O_NONBLOCK); 34 | if (-1 == mqd) 35 | { 36 | perror("mq_open error"); 37 | exit(-1); 38 | } 39 | ret = mq_getattr(mqd, &attr); 40 | if (-1 == ret) 41 | { 42 | perror("mq_getattr error"); 43 | exit(-1); 44 | } 45 | buff = malloc(attr.mq_msgsize); //buff的空间要不小于attr的msgsize成员,否则mq_receive会返回EMSGSIZE错误 46 | assert(buff); 47 | 48 | sigemptyset(&zeromask); 49 | sigemptyset(&newmask); 50 | sigemptyset(&oldmask); 51 | sigaddset(&newmask, SIGUSR1); 52 | 53 | signal(SIGUSR1, sig_usr1); 54 | sigev.sigev_notify= SIGEV_SIGNAL; 55 | sigev.sigev_signo = SIGUSR1; 56 | ret = mq_notify(mqd, &sigev); 57 | if (-1 == ret) 58 | { 59 | perror("mq_notify err"); 60 | exit(-1); 61 | } 62 | 63 | for (;;) 64 | { 65 | sigprocmask(SIG_BLOCK, &newmask, &oldmask); 66 | while (0 == mqflag) 67 | { 68 | sigsuspend(&zeromask); 69 | } 70 | mqflag = 0; // reset flag 71 | 72 | mq_notify(mqd, &sigev); 73 | while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) 74 | { 75 | printf("read %ld bytes\n", (long)n); 76 | } 77 | if (errno != EAGAIN) // 表示暂无消息可读,属于正常现象 78 | { 79 | perror("mq_receive error"); 80 | exit(-1); 81 | } 82 | sigprocmask(SIG_UNBLOCK, &newmask, NULL); 83 | } 84 | 85 | return 0; 86 | 87 | } 88 | 89 | static void sig_usr1(int signo) 90 | { 91 | mqflag = 1; 92 | return; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/mq_notify02.c: -------------------------------------------------------------------------------- 1 | /* 2 | 使用sigwait代替信号处理程序的信号通知 3 | 调用sigwait前,我们阻塞某个信号集。我们将这个信号集指定为set参数。sigwait然后一直阻塞到这些信号中有一个或 4 | 多个待处理,这时它返回一个信号(存放在指针sig中)。这个过程称为“同步地等待一个异步事件” 5 | 6 | 大多数讨论线程的书,推荐在多线程化的进程中使用sigwait来处理所有信号,而绝不要使用异步信号处理程序 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | int main(int argc, char **argv) 19 | { 20 | int signo; 21 | mqd_t mqd; 22 | void *buff = NULL; 23 | ssize_t n; 24 | sigset_t newmask; 25 | struct mq_attr attr; 26 | struct sigevent sigev; 27 | int ret = 0; 28 | 29 | if (argc != 2) 30 | { 31 | fprintf(stdout, "usage: mq_notify02 \n"); 32 | exit(-1); 33 | } 34 | 35 | mqd = mq_open(argv[1], O_RDONLY | O_NONBLOCK); 36 | if (-1 == mqd) 37 | { 38 | perror("mq_open error"); 39 | exit(-1); 40 | } 41 | ret = mq_getattr(mqd, &attr); 42 | if (-1 == ret) 43 | { 44 | perror("mq_getattr error"); 45 | exit(-1); 46 | } 47 | buff = malloc(attr.mq_msgsize); //buff的空间要不小于attr的msgsize成员,否则mq_receive会返回EMSGSIZE错误 48 | 49 | sigemptyset(&newmask); 50 | sigaddset(&newmask, SIGUSR1); 51 | sigprocmask(SIG_BLOCK, &newmask, NULL); //block SIGUSR1 52 | 53 | sigev.sigev_notify= SIGEV_SIGNAL; 54 | sigev.sigev_signo = SIGUSR1; 55 | ret = mq_notify(mqd, &sigev); 56 | if (-1 == ret) 57 | { 58 | perror("mq_notify err"); 59 | exit(-1); 60 | } 61 | 62 | for (;;) 63 | { 64 | //sigwait调用会阻塞并等待SIGUSR1的递交 65 | ret = sigwait(&newmask, &signo); 66 | if (0 != ret) 67 | { 68 | fprintf(stderr, "sigwait error:%d\n", ret); 69 | exit(-1); 70 | } 71 | 72 | 73 | if (SIGUSR1 == signo) 74 | { 75 | mq_notify(mqd, &sigev); // 重新注册通知 76 | 77 | // 读出所有的可用消息 78 | while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) 79 | { 80 | printf("read %ld bytes\n", (long)n); 81 | } 82 | if (errno != EAGAIN) 83 | { 84 | perror("mq_receive error"); 85 | exit(-1); 86 | } 87 | } 88 | } 89 | 90 | return 0; 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /openssl_demo/openssl_sign_verify.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | const int MSG_LEN = 128+1; 9 | const char *PUBKEY_FILE = "public.rsa"; 10 | const char *PRIKEY_FILE = "private.rsa"; 11 | 12 | void print_hex(char* buff) 13 | { 14 | for (int i=0; buff[i]; i++) 15 | printf("%02x", (unsigned char)buff[i]); 16 | printf("\n"); 17 | } 18 | 19 | int rsa_verify(char *in, const char *key_path, char* in2, int len) 20 | { 21 | RSA *p_rsa; 22 | FILE *file; 23 | if ((file=fopen(key_path, "r"))==NULL) 24 | { 25 | perror("open key file error"); 26 | return 0; 27 | } 28 | //if ((p_rsa=PEM_read_RSA_PUBKEY(file, NULL, &ccbb, NULL))==NULL){ 29 | if ((p_rsa=PEM_read_RSAPublicKey(file, NULL, NULL, NULL))==NULL) 30 | { 31 | ERR_print_errors_fp(stdout); 32 | return 0; 33 | } 34 | if (!RSA_verify(NID_md5, (unsigned char*)in, strlen(in), (unsigned char*)in2, len, p_rsa)) 35 | { 36 | return 0; 37 | } 38 | RSA_free(p_rsa); 39 | fclose(file); 40 | return 1; 41 | } 42 | 43 | int rsa_sign(char *in, const char *key_path, char* out, int* plen) 44 | { 45 | RSA *p_rsa; 46 | FILE *file; 47 | if ((file=fopen(key_path, "r"))==NULL) 48 | { 49 | perror("open key file error"); 50 | return 0; 51 | } 52 | if ((p_rsa=PEM_read_RSAPrivateKey(file, NULL, NULL, NULL))==NULL) 53 | { 54 | ERR_print_errors_fp(stdout); 55 | return 0; 56 | } 57 | if (!RSA_sign(NID_md5, (unsigned char*)in, strlen(in), (unsigned char*)out, (unsigned int*)plen, p_rsa)) 58 | { 59 | return 0; 60 | } 61 | RSA_free(p_rsa); 62 | fclose(file); 63 | return 1; 64 | } 65 | 66 | int main(int argc, char**argv) 67 | { 68 | char text[MSG_LEN] = "this is the data to be signed"; 69 | char sign[MSG_LEN] = {}; 70 | int len=0; 71 | 72 | 73 | if (!rsa_sign(text, PRIKEY_FILE, sign, &len)) 74 | { 75 | printf("sign error\n"); 76 | return -1; 77 | } 78 | printf("sign %lu:", strlen((char*)sign)); 79 | print_hex(sign); 80 | 81 | if (!rsa_verify(text, PUBKEY_FILE, sign, len)) 82 | { 83 | printf("verify error\n"); 84 | return -1; 85 | } 86 | printf("verify ok\n"); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /pthread/pthread_dotprod_mutex.c: -------------------------------------------------------------------------------- 1 | /* 2 | this example program illustrates the use of mutex variables in a threads program. 3 | this version was updated from pthread_dotprod_serial.c. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | double *a; 12 | double *b; 13 | double sum; 14 | int veclen; 15 | } DOTDATA; 16 | 17 | #define NUMTHRDS 4 18 | #define VECLEN 100000 19 | 20 | DOTDATA dotstr; 21 | pthread_t callThd[NUMTHRDS]; 22 | pthread_mutex_t mutexsum; 23 | 24 | void *dotprod(void *arg) 25 | { 26 | int i, start, end, len; 27 | long offset; 28 | double mysum, *x, *y; 29 | offset = (long)arg; 30 | 31 | len = dotstr.veclen; 32 | start = offset*len; 33 | end = start+len; 34 | x = dotstr.a; 35 | y = dotstr.b; 36 | 37 | mysum = 0; 38 | for (i=start; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../../unpipc.h" 10 | 11 | #define NBUFF 10 12 | 13 | typedef struct 14 | { 15 | int buff[NBUFF]; 16 | sem_t mutex; 17 | sem_t nempty; 18 | sem_t nstored; 19 | } Shared; 20 | 21 | int nitems; // read only by producer and consumer 22 | Shared shared; 23 | 24 | void *produce(void *); 25 | void *consume(void *); 26 | 27 | int main(int argc, char **argv) 28 | { 29 | pthread_t tid_produce; 30 | pthread_t tid_consume; 31 | 32 | if (argc != 2) 33 | { 34 | printf("usage: %s <#items>", argv[0]); 35 | return -1; 36 | } 37 | 38 | nitems = atoi(argv[1]); 39 | 40 | // create the semaphores 41 | sem_init(&shared.mutex, 0, 1); 42 | sem_init(&shared.nempty, 0, NBUFF); 43 | sem_init(&shared.nstored, 0, 0); 44 | 45 | // create one producer and one consumer thread 46 | pthread_create(&tid_produce, NULL, produce, NULL); 47 | pthread_create(&tid_consume, NULL, consume, NULL); 48 | 49 | // wait for the two threads 50 | pthread_join(tid_produce, NULL); 51 | pthread_join(tid_consume, NULL); 52 | 53 | // remove the semaphores 54 | sem_destroy(&shared.mutex); 55 | sem_destroy(&shared.nempty); 56 | sem_destroy(&shared.nstored); 57 | 58 | return 0; 59 | } 60 | 61 | void *produce(void *arg) 62 | { 63 | int i = 0; 64 | 65 | for (i=0; i 9 | int pipe(int fd[2]); 10 | 返回: 成功返回0, 出错返回-1 11 | 12 | 该函数返回两个文件描述符: fd[0]和fd[1], 前者打开来读, 后者打开来写. 13 | 14 | ``` 15 | 16 | 另一个关于管道的例子, 标准I/O函数库提供了popen函数, 它创建一个管道并启动另一个 17 | 进程, 该进程要么从该管道读出标准输入, 要么往该管道写入标准输出 18 | 19 | ```cpp 20 | #include 21 | 22 | FILE *popen(const char *command, const char *type); 23 | 返回: 成功返回文件指针,失败返回NULL 24 | 注意: popen不对标准错误输出做任何处理, 只有标准输出才被重定向到由它创建的管道 25 | 26 | int pclose(FILE *stream); 27 | 返回: 成功则为shell的终止状态, 失败为-1 28 | 29 | command是一个shell命令行, popen在调用进程和所指定的命令之间创建一个管道 30 | 31 | - 如果type为r, 调用进程读入command的标准输出 32 | - 如果type为w, 调用进程写到command的标准输入 33 | 34 | ``` 35 | 36 | * pipe01.c演示了父子进程间通过pipe实现半双工通信 37 | * pipe02.c演示了使用popen创建管道 38 | 39 | ###FIFO 有名管道 40 | 41 | 每个FIFO有一个路径名与之关联, 从而允许无亲缘关系的进程访问同一个FIFO。 42 | 43 | ```cpp 44 | #include 45 | #include 46 | 47 | inf mkfifo(const char *pathname, mode_t mode); 48 | 返回: 成功返回0, 失败返回-1 49 | 50 | mkfifo函数已经隐含指定了O_CREAT | O_EXCL, 也就是说, 它要么创建一个新的FIFO, 51 | 要么返回一个EEXIST错误(如果所指定名字的FIFO已经存在)。此处可参考示例中的正 52 | 确创建FIFO的步骤 53 | 54 | - 创建出一个FIFO后, 它必须或者打开来读, 或者打开来写。不能打开来既读又写, 55 | 因为它是**半双工**的 56 | - 如果一个FIFO, 当前尚没有进程打开它来写, 那么此时打开该FIFO来读的进程将会阻塞 57 | - 对管道或FIFO的write总是往末尾添加数据, 对它们的read总是从开头返回数据。 58 | - 如果对管道或FIFO执行lseek, 会返回ESPIPE错误 59 | - 当对一个管道或FIFO的最终close发生时, 该管道或FIFO中的任何残留数据都被丢弃 60 | 61 | ``` 62 | 63 | * fifo_read.c 中从文件data.txt中读取内容, 写入到FIFO中 64 | * fifo_write.c 中从FIFO中读取内容, 写入到datafromfifo.txt中 65 | * data.txt 是测试文件 66 | * datafromfifo.txt 是fifo_write.c运行后生成的文件 67 | 68 | ###管道和FIFO的区别 69 | 70 | * 创建并打开一个管道, 只需要调用pipe; 71 | 创建并打开一个FIFO则需在调用mkdifo后再调用open 72 | * 管道在所有进程最终都关闭它之后自动消失。 73 | FIFO的名字则只有通过调用unlink才从文件系统中删除 74 | * FIFO需要额外调用的好处: FIFO在文件系统中有一个名字, 该名字允许某个进程创建一个 75 | FIFO, 与它**无亲缘关系**的 另一个进程来打开这个FIFO, 这对管道来说是不可能的( 76 | 不考虑传递描述符的情况) 77 | 78 | ###管道和FIFO的限制 79 | 80 | 系统加于管道和FIFO的唯一限制为: 81 | 82 | * OPEN_MAX 一个进程在任意时刻打开的最大描述符数 83 | * PIPE_BUF 可原子地写往一个管道或FIFO的最大数据量 84 | 85 | * get_sys_conf.c 获取当前系统的OPEN_MAX和PIPE_BUF值 86 | 87 | 88 | ###将一个描述符设为非阻塞两种方式 89 | 90 | 1. 调用open的时候可指定O_NONBLOCK标志 91 | 2. 如果一个描述符已打开, 那么可以调用fcntl以启用O_NONBLOCK标志。 92 | 对于管道来说, 必须使用这种技术, 因为管道没有open调用, 在pipe中也无法指定O_NONBLOCK标志 93 | 94 | **FIFO的真正优势**表现在服务器可以是一个长期运行的进程(例如守护进程), 而且与其客户可以无亲缘关系。 95 | 作为服务器的守护进程以某个众所周知的路径名创建一个FIFO, 并打开该FIFO来读。此后某个 96 | 时刻启动的客户打开该FIFO来写, 并将其命令或给守护进程的其他任何东西通过该FIFO发送出去。 97 | 使用FIFO很容易实现这种形式的单向通信(client->server)。如果守护进程需要向客户发送 98 | 回一些东西, 那就需要点技巧(例如客户需要通知守护进程要打开哪个FIFO可以给其发消息) 99 | 100 | -------------------------------------------------------------------------------- /network/strcliselect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #define MAXLINE 1024 12 | #define SERV_PORT 9877 13 | 14 | #define min(a,b) ((a) < (b) ? (a) : (b)) 15 | #define max(a,b) ((a) > (b) ? (a) : (b)) 16 | 17 | void str_cli(FILE *fp, int sockfd) 18 | { 19 | int maxfdp1, stdineof; 20 | fd_set rset; 21 | char sendline[MAXLINE], recvline[MAXLINE]; 22 | int n, ret; 23 | 24 | printf("in str_cli\n"); 25 | stdineof = 0; 26 | FD_ZERO(&rset); 27 | while (1) 28 | { 29 | if (stdineof == 0) 30 | FD_SET(fileno(fp), &rset); 31 | FD_SET(sockfd, &rset); 32 | maxfdp1 = max(fileno(fp), sockfd) + 1; 33 | 34 | assert(-1 != select(maxfdp1, &rset, NULL, NULL, NULL)); 35 | 36 | if (FD_ISSET(sockfd, &rset)) 37 | { 38 | if (0 == (n = recv(sockfd, recvline, sizeof(recvline), 0))) 39 | { 40 | printf("recv 0\n"); 41 | if (stdineof == 1) 42 | { 43 | return; 44 | } 45 | else 46 | { 47 | printf("server terminated prematurely\n"); 48 | return; 49 | } 50 | } 51 | printf("recv %d\n", n); 52 | write(stdout, recvline, n); 53 | } 54 | 55 | if (FD_ISSET(fileno(fp), &rset)) 56 | { 57 | if ((n = read(fileno(fp), sendline, sizeof(sendline))) == 0) 58 | { 59 | printf("read 0\n"); 60 | stdineof = 1; 61 | shutdown(sockfd, SHUT_WR); //send FIN 62 | FD_CLR(fileno(fp), &rset); 63 | continue; 64 | } 65 | printf("read %d\n", n); 66 | send(sockfd, sendline, n, 0); 67 | } 68 | } 69 | } 70 | 71 | int main(int argc, char **argv) 72 | { 73 | int sockfd; 74 | struct sockaddr_in servaddr; 75 | int ret = 0; 76 | 77 | if (argc != 2) 78 | { 79 | printf("usage: tcpcli \n"); 80 | return 0; 81 | } 82 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 83 | assert(sockfd > 0); 84 | 85 | bzero(&servaddr, sizeof(servaddr)); 86 | servaddr.sin_family = AF_INET; 87 | servaddr.sin_port = htons(SERV_PORT); 88 | inet_pton(AF_INET, argv[1], &servaddr.sin_addr); 89 | 90 | ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 91 | assert(ret == 0); 92 | 93 | str_cli(stdin, sockfd); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /ipc/posix_msg_queue/signal_realtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef void (sigfunc_rt)(int, siginfo_t *, void *); 8 | static void sig_rt(int signo, siginfo_t *info, void *context); 9 | sigfunc_rt *signal_rt(int signo, sigfunc_rt *func, sigset_t *mask); 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int i, j; 14 | pid_t pid; 15 | sigset_t newset; 16 | union sigval val; 17 | 18 | printf("SIGRTMIN=%d, SIGRTMAX=%d\n", (int)SIGRTMIN, (int)SIGRTMAX); 19 | 20 | if ((pid = fork()) == 0) 21 | { 22 | sigemptyset(&newset); 23 | sigaddset(&newset, SIGRTMAX); 24 | sigaddset(&newset, SIGRTMAX-1); 25 | sigaddset(&newset, SIGRTMAX-2); 26 | sigprocmask(SIG_BLOCK, &newset, NULL); // block signal SIGRTMAX SIGRTMAX-1 SIGRTMAX-2 27 | 28 | signal_rt(SIGRTMAX, sig_rt, &newset); // signal_rt set flag SA_SIGINFO 29 | signal_rt(SIGRTMAX-1, sig_rt, &newset); 30 | signal_rt(SIGRTMAX-2, sig_rt, &newset); 31 | 32 | sleep(6); // let parent send 9 signals 33 | 34 | sigprocmask(SIG_UNBLOCK, &newset, NULL); 35 | sleep(3); // let sig_rt call printf 9 times 36 | exit(0); 37 | } 38 | 39 | // parent sends 9 signals to child 40 | sleep(3); // let child block all signals 41 | printf("SIQUEUE=%d\n", SI_QUEUE); 42 | for (i=SIGRTMAX; i>=SIGRTMAX-2; i--) 43 | { 44 | for (j=0; j<=2; j++) 45 | { 46 | val.sival_int = j; 47 | sigqueue(pid, i, val); // send signals; we expect that the smaller signal should be sent first 48 | printf("sent signal %d, val = %d\n", i, j); 49 | } 50 | } 51 | 52 | exit(0); 53 | } 54 | 55 | static void sig_rt(int signo, siginfo_t *info, void *context) 56 | { 57 | // code==-1==SI_QUEUE 58 | printf("received signal #%d, code = %d, ival = %d\n", 59 | signo, info->si_code, info->si_value.sival_int); 60 | } 61 | 62 | 63 | sigfunc_rt *signal_rt(int signo, sigfunc_rt *func, sigset_t *mask) 64 | { 65 | struct sigaction act, oact; 66 | 67 | act.sa_sigaction = func; // must store function addr here 68 | act.sa_mask = *mask; // signals to block 69 | act.sa_flags = SA_SIGINFO; // must specify this for realtime 70 | if (SIGALRM == signo) 71 | { 72 | #ifdef SA_INTERRUPT 73 | act.sa_flags |= SA_INTERRUPT; 74 | #endif 75 | } 76 | else 77 | { 78 | #ifdef SA_RESTART 79 | act.sa_flags |= SA_RESTART; 80 | #endif 81 | } 82 | 83 | if (sigaction(signo, &act, &oact) < 0) 84 | { 85 | return ((sigfunc_rt *)SIG_ERR); 86 | } 87 | 88 | return oact.sa_sigaction; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /utility/seml01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | union semun 11 | { 12 | int val; 13 | struct semid_ds *buf; 14 | unsigned short *arry; 15 | }; 16 | 17 | static int sem_id = 0; 18 | static int set_semvalue(); 19 | static void del_semvalue(); 20 | static int semaphore_p(); 21 | static int semaphore_v(); 22 | 23 | int main(int argc, char **argv) 24 | { 25 | char message = 'X'; 26 | int i = 0; 27 | 28 | sem_id = semget((key_t)1234, 1, 0666|IPC_CREAT); 29 | 30 | if (argc > 1) 31 | { 32 | if (!set_semvalue()) 33 | { 34 | fprintf(stderr, "failed to initialize semaphore\n"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | message = argv[1][0]; 39 | sleep(1); 40 | } 41 | 42 | for (i=0; i<10; i++) 43 | { 44 | if (!semaphore_p()) 45 | exit(EXIT_FAILURE); 46 | printf("%c", message); 47 | fflush(stdout); 48 | sleep(2); 49 | printf("%c", message); 50 | fflush(stdout); 51 | if (!semaphore_v()) 52 | exit(EXIT_FAILURE); 53 | sleep(2); 54 | } 55 | 56 | sleep(10); 57 | printf("\n%d - finished\n", getpid()); 58 | 59 | if (argc > 1) 60 | { 61 | sleep(3); 62 | del_semvalue(); 63 | } 64 | 65 | exit(EXIT_SUCCESS); 66 | } 67 | 68 | static int set_semvalue() 69 | { 70 | union semun sem_union = {}; 71 | sem_union.val = 1; 72 | if (semctl(sem_id, 0, SETVAL, sem_union) == -1) 73 | { 74 | return 0; 75 | } 76 | return 1; 77 | } 78 | 79 | static void del_semvalue() 80 | { 81 | union semun sem_union = {}; 82 | if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1) 83 | { 84 | fprintf(stderr, "failed to delete semaphore\n"); 85 | } 86 | } 87 | 88 | static int semaphore_p() 89 | { 90 | struct sembuf sem_b; 91 | sem_b.sem_num = 0;//除非使用一组信号量,否则它为0 92 | sem_b.sem_op = -1;//信号量在一次操作中需要改变的数据, -1,即P操作, +1,即V操作 93 | sem_b.sem_flg = SEM_UNDO;//是操作系统跟踪信号,在进程没有释放信号量而终止时,操作系统释放信号量 94 | if (semop(sem_id, &sem_b, 1) == -1) 95 | { 96 | fprintf(stderr, "semaphore_p failed\n"); 97 | return 0; 98 | } 99 | return 1; 100 | } 101 | 102 | static int semaphore_v() 103 | { 104 | struct sembuf sem_v; 105 | sem_v.sem_num = 0; 106 | sem_v.sem_op = 1; 107 | sem_v.sem_flg = SEM_UNDO; 108 | if (semop(sem_id, &sem_v, 1) == -1) 109 | { 110 | fprintf(stderr, "semaphore_v failed\n"); 111 | return 0; 112 | } 113 | return 1; 114 | 115 | } 116 | -------------------------------------------------------------------------------- /py/log_advanced/logging_config_with_dictfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- encoding: utf-8 -*- 3 | 4 | import logging 5 | import logging.config 6 | 7 | ''' 8 | logging.config.dictConfig(config) 9 | 10 | Takes the logging configuration from a dictionary. 11 | 12 | If an error is encountered during configuration, this function will 13 | raise a ValueError, TypeError, AttributeError or ImportError with a 14 | suitably descriptive message. The following is a (possibly incomplete) 15 | list of conditions which will raise an error: 16 | * A level which is not a string or which is a string not 17 | corresponding to an actual logging level. 18 | * A propagate value which is not a boolean. 19 | * An id which does not have a corresponding destination. 20 | * A non-existent handler id found during an incremental call. 21 | * An invalid logger name. 22 | * Inability to resolve to an internal or external object. 23 | 24 | ''' 25 | 26 | LOG_SETTINGS = { 27 | 'version': 1, 28 | 'formatters': { 29 | 'brief':{ # configuration for formatter with id "brief" goes here 30 | 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 31 | }, 32 | 'precise':{ # configuration for formatter with id "precise" goes here 33 | 'format': '%(asctime)s - %(name)s - %(message)s' 34 | } 35 | }, 36 | 'handlers': { 37 | 'console':{ # This is an id 38 | # configuration of handler with id "console" goes here 39 | 'class': 'logging.StreamHandler', 40 | 'level': 'DEBUG', 41 | 'formatter': 'brief', 42 | 'stream': 'ext://sys.stdout' 43 | }, 44 | 'file':{ # This is another id 45 | # configuration of handler with id "file" goes here 46 | 'class': 'logging.handlers.RotatingFileHandler', 47 | 'formatter': 'precise', 48 | 'filename': 'log_dict.log', 49 | 'maxBytes': 1024, 50 | 'backupCount': 3 51 | } 52 | }, 53 | 'loggers':{ 54 | 'logging_dict_conf':{ 55 | # other configuration for logger "logging_dict_conf" 56 | 'level': 'DEBUG', 57 | 'handlers': ['console', 'file'], 58 | 'propagate': 'no' 59 | } 60 | }, 61 | 'root':{ 62 | 'level': 'DEBUG', 63 | # 'handlers': ['console'], # uncomment this will result log printed on screen one more time 64 | } 65 | } 66 | 67 | logging.config.dictConfig(LOG_SETTINGS) 68 | 69 | logger = logging.getLogger("logging_dict_conf") 70 | logger.info("log from dict_conf") 71 | 72 | logger2 = logging.getLogger("logging_dict_conf") 73 | new_handler = logging.FileHandler("new_handler.log") 74 | logger2.handler = [] 75 | logger2.addHandler(new_handler) 76 | logger2.info("log for logger2") 77 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/Serv_server.skeleton.cpp: -------------------------------------------------------------------------------- 1 | // This autogenerated skeleton file illustrates how to build a server. 2 | // You should copy it to another filename to avoid overwriting it. 3 | 4 | #include "Serv.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace ::apache::thrift; 14 | using namespace ::apache::thrift::protocol; 15 | using namespace ::apache::thrift::transport; 16 | using namespace ::apache::thrift::server; 17 | using namespace ::apache::thrift::concurrency; 18 | 19 | using boost::shared_ptr; 20 | 21 | #define THREAD_NUM 2 22 | const int g_port = 9090; 23 | 24 | class ServHandler : virtual public ServIf { 25 | public: 26 | ServHandler() { 27 | // Your initialization goes here 28 | } 29 | 30 | void put(const Student& s) { 31 | // Your implementation goes here 32 | printf("put\n"); 33 | std::cout < handler(new ServHandler()); 42 | shared_ptr processor(new ServProcessor(handler)); 43 | shared_ptr protocolFactory(new TBinaryProtocolFactory()); 44 | 45 | shared_ptr threadManager = ThreadManager::newSimpleThreadManager(THREAD_NUM); 46 | shared_ptr threadFactory = shared_ptr (new PosixThreadFactory()); 47 | threadManager->threadFactory(threadFactory); 48 | threadManager->start(); 49 | TNonblockingServer server(processor, protocolFactory, g_port, threadManager); 50 | 51 | try 52 | { 53 | server.serve(); 54 | } 55 | catch (TException e) 56 | { 57 | printf("Server.serve() failed\n"); 58 | exit(-1); 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | int main(int argc, char **argv) 65 | { 66 | thrift_server_run(); 67 | while (1) 68 | { 69 | sleep(10); 70 | } 71 | return 0; 72 | } 73 | #endif 74 | 75 | #ifdef SIMPLE_SERVER 76 | int main(int argc, char **argv) { 77 | int port = 9090; 78 | shared_ptr handler(new ServHandler()); 79 | shared_ptr processor(new ServProcessor(handler)); 80 | shared_ptr serverTransport(new TServerSocket(port)); 81 | shared_ptr transportFactory(new TBufferedTransportFactory()); 82 | shared_ptr protocolFactory(new TBinaryProtocolFactory()); 83 | 84 | TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); 85 | server.serve(); 86 | return 0; 87 | } 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /ipc/mutex_cond/prodcons_mutex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../unpipc.h" 8 | 9 | 10 | int nitems; // read-only by producer and consumer 11 | 12 | struct 13 | { 14 | pthread_mutex_t mutex; 15 | int buff[MAXNITEMS]; 16 | int nput; // next index to store 17 | int nval; // next value to store 18 | } shared = {PTHREAD_MUTEX_INITIALIZER}; 19 | 20 | void *produce(void *); 21 | void *consume(void *); 22 | 23 | int main(int argc, char **argv) 24 | { 25 | int i, nthreads, count[MAXNTHREADS]; 26 | pthread_t tid_produce[MAXNTHREADS], tid_consume; 27 | 28 | if (argc != 3) 29 | { 30 | fprintf(stdout, "usage: prodcons_mutex <#items> <#threads>\n"); 31 | exit(-1); 32 | } 33 | 34 | nitems = MIN(atoi(argv[1]), MAXNITEMS); 35 | nthreads = MIN(atoi(argv[2]), MAXNTHREADS); 36 | 37 | // start all producers and one consumer 38 | for (i=0; i= nitems) 62 | { 63 | pthread_mutex_unlock(&shared.mutex); 64 | return NULL; // array is full ,we're done 65 | } 66 | 67 | shared.buff[shared.nput] = shared.nval; 68 | shared.nput++; 69 | shared.nval++; 70 | pthread_mutex_unlock(&shared.mutex); 71 | *((int *)arg) += 1; 72 | } 73 | } 74 | 75 | static void consume_wait(int i) 76 | { 77 | for (;;) 78 | { 79 | pthread_mutex_lock(&shared.mutex); 80 | if (i < shared.nput) 81 | { 82 | pthread_mutex_unlock(&shared.mutex); 83 | return ; // an item is ready 84 | } 85 | // 这里的lock->unlock->lock...被称为轮询,也是对CPU的浪费 86 | // 这里用条件变量会更好,它允许一个线程睡眠到某个事件发生 87 | // 为止 88 | pthread_mutex_unlock(&shared.mutex); 89 | } 90 | } 91 | 92 | void *consume(void *arg) 93 | { 94 | int i; 95 | for (i=0; i 20 | 21 | int fcntl(int fd, int cmd, ... /*struct flock *arg */); 22 | 返回: 23 | 24 | // 用于记录上锁的cmd参数有3个值。这3个cmd要求第3个参数arg是指向struct flock的指针 25 | struct flock 26 | { 27 | short l_type; // F_RDLCK, F_WRLCK, F_UNLCK 28 | short l_whence; // SEEK_SET, SEEK_CUR, SEEK_END 29 | off_t l_start; // relative starting offset in bytes 30 | off_t l_len; // #bytes; 0 means until end-of-file 31 | pid_t l_pid; // PID returned by F_GETLK 32 | } 33 | 34 | ``` 35 | 36 | * F_SETLK 获取(l_type为**F_RDLCK**或**F_WRLCK**)或释放(l_type为**F_UNLCK**)由 37 | arg指向的flock结构所描述的锁,如果无法将该锁授予调用进程,该函数就立即返回一个 38 | EACCESS或EAGAIN错误,并**不阻塞** 39 | * F_SETLKW 该命令与上一个命令类似,不过在无法获取锁请求的锁时,调用线程将**阻塞** 40 | * F_GETLK 检查由arg指向的锁以确定是否有某个已存在的锁会妨碍将新锁授予调用线程。如 41 | 果当前没有这样的锁存在,由arg指向的struct flock的l_type成员就被置为F_UNLCK。否则, 42 | 关于这个已存在锁的信息将在由arg指向的struct flock中返回,其中包含持有该锁的进程ID 43 | 44 | **注意:** 45 | 46 | 1. F_GETLK后紧接着F_SETLK**不是一个原子操作**,并不能保证F_SETLK会成功,因为在两个函 47 | 数执行期间,很可能有另一个进程已经获取了我们想要的锁。 48 | >提供F_GETLK的原因在于:当执行F_SETLK的fcntl返回一个错误时,导致该错误的某个锁的 49 | 信息可由F_GETLK来返回,从而允许我们确定是哪个进程锁住了所请求的文件区,以及上锁方 50 | 式。但同样的原因,这两个操作**不是原子操作**,在F_GETLK调用之前,很可能原来持有锁 51 | 的进程已经释放了锁。 52 | 53 | 2. 对于一个文件的任意字节,**同一时刻**,最多只能存在一种类型的锁(读出锁或写入锁), 54 | 而且,一个给定字节可以有**多个读出锁,但只能有一个写入锁**。 55 | 3. 当一个描述符不是打开用来读时,如果对它请求一个读出锁,错误就会发生;同样,当一个 56 | 描述符不是打开用来写时,如果对它请求一个写入锁,错误也会发生 57 | 4. 对于一个打开着某个文件的给定进程来说,当它关闭该文件的所有描述符或它本身终止时,与 58 | 该文件关联的所有锁都被删除。**锁不能通过fork由子进程继承** 59 | 5. 记录上锁不应该同标准I/O函数库一起使用,因为该函数库会执行内部缓冲。当某个文件需要上 60 | 锁时,为避免问题,应对它使用read和write。 61 | > 在进程终止时由内核完成已有锁清理工作的特性,只有fcntl记录上锁完全提供了,System V 62 | 信号量把它作为一个选项提供。互斥锁、条件变量、读写锁、Posix信号量,并不在进程终止时 63 | 执行清理工作。 64 | 65 | 6. 锁住整个文件的两种方式 66 | * l_whence=SEEK_SET, l_start=0, l_len=0(常用,只需一个函数调用) 67 | * 使用lseek把读写指针定位到文件头,然后指定l_whence=SEEK_CUR, l_start=0, l_len=0 68 | 69 | **劝告性上锁** 70 | 71 | Posix记录上锁称为劝告性上锁。其含义是内核维护着已由各个进程上锁的所有文件的正确信息, 72 | 但是它不能防止一个进程写已由另一个进程读锁定的某个文件;类似的,它也不能防止一个进程 73 | 读已由另一个进程写锁定的某个文件。一个进程能够无视一个劝告性锁而写一个读锁定文件,或 74 | 者读一个写锁定文件,当然,前提是该进程有读或写该文件的足够权限。 75 | 76 | **强制性上锁** 77 | 78 | 可以用`chmod +l filename`来对某个文件启用强制性上锁 79 | 强制性上锁虽然能够阻止非协作进程读一个已被锁住的文件,但是也**不能保证万无一失**。 80 | 81 | **建议:**如果有多个进程在更新同一个文件,那么所有进程必须使用某种上锁形式协作。 82 | 83 | **读出者和写入者的优先级** 84 | 85 | 不同的系统可能有不同的实现,有的是以FIFO顺序处理上锁请求的,而不管上锁请求的类型; 86 | 有的则会优先考虑读出请求 87 | 88 | **启动一个守护进程的唯一副本** 89 | 90 | 记录上锁的一个常见用途是确保某个程序(如守护程序)在任何时刻只有一个副本在运行。 91 | >守护进程维护一个只有1行文本的文件,其中包含它的进程ID。它打开这个文件,必要的 92 | 时候创建它,然后请求整个文件的一个写入锁。如果没有取得该锁,我们就知道该程序有 93 | 另一个副本在运行,于是输出一个出错信息并终止。 94 | 95 | 如果某个守护进程提前崩溃了,内核会**自动释放**它的记录锁。 96 | 97 | -------------------------------------------------------------------------------- /openssl_demo/aes_demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define AES_BITS 128 7 | #define MSG_LEN 128 8 | 9 | int aes_encrypt(char* in, char* key, char* out)//, int olen)可能会设置buf长度 10 | { 11 | if(!in || !key || !out) 12 | { 13 | return 0; 14 | } 15 | 16 | unsigned char iv[AES_BLOCK_SIZE] = {}; 17 | for(int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../unpipc.h" 8 | 9 | 10 | int nitems; // read-only by producer and consumer 11 | int buff[MAXNITEMS]; 12 | 13 | struct 14 | { 15 | pthread_mutex_t mutex; 16 | int nput; // next index to store 17 | int nval; // next value to store 18 | } put = {PTHREAD_MUTEX_INITIALIZER}; 19 | 20 | struct 21 | { 22 | pthread_mutex_t mutex; 23 | pthread_cond_t cond; 24 | int nready; // number ready for consumer 25 | } nready = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER}; 26 | 27 | 28 | void *produce(void *); 29 | void *consume(void *); 30 | 31 | int main(int argc, char **argv) 32 | { 33 | int i, nthreads, count[MAXNTHREADS]; 34 | pthread_t tid_produce[MAXNTHREADS], tid_consume; 35 | 36 | if (argc != 3) 37 | { 38 | fprintf(stdout, "usage: prodcons_mutex <#items> <#threads>\n"); 39 | exit(-1); 40 | } 41 | 42 | nitems = MIN(atoi(argv[1]), MAXNITEMS); 43 | nthreads = MIN(atoi(argv[2]), MAXNTHREADS); 44 | 45 | // start all producers and one consumer 46 | for (i=0; i= nitems) 72 | { 73 | pthread_mutex_unlock(&put.mutex); 74 | return NULL; 75 | } 76 | 77 | buff[put.nput] = put.nval; 78 | put.nput++; 79 | put.nval++; 80 | pthread_mutex_unlock(&put.mutex); 81 | 82 | pthread_mutex_lock(&nready.mutex); 83 | dosignal = (nready.nready == 0); 84 | nready.nready++; 85 | pthread_mutex_unlock(&nready.mutex); 86 | 87 | if (dosignal) 88 | { 89 | pthread_cond_signal(&nready.cond); 90 | } 91 | *((int *)arg) += 1; 92 | } 93 | } 94 | 95 | void *consume(void *arg) 96 | { 97 | int i; 98 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../../unpipc.h" 10 | 11 | #define NBUFF 10 12 | 13 | const char *SEM_MUTEX = "mutex"; 14 | const char *SEM_NEMPTY = "nempty"; 15 | const char *SEM_NSTORED = "nstored"; 16 | 17 | typedef struct 18 | { 19 | int buff[NBUFF]; 20 | sem_t *mutex; 21 | sem_t *nempty; 22 | sem_t *nstored; 23 | } Shared; 24 | 25 | int nitems; // read only by producer and consumer 26 | Shared shared; 27 | 28 | void *produce(void *); 29 | void *consume(void *); 30 | 31 | int main(int argc, char **argv) 32 | { 33 | pthread_t tid_produce; 34 | pthread_t tid_consume; 35 | 36 | if (argc != 2) 37 | { 38 | printf("usage: %s <#items>", argv[0]); 39 | return -1; 40 | } 41 | 42 | nitems = atoi(argv[1]); 43 | 44 | // create the semaphores 45 | shared.mutex = sem_open(SEM_MUTEX, O_CREAT | O_EXCL, FILE_MODE, 1); 46 | shared.nempty = sem_open(SEM_NEMPTY, O_CREAT | O_EXCL, FILE_MODE, NBUFF); 47 | shared.nstored = sem_open(SEM_NSTORED, O_CREAT | O_EXCL, FILE_MODE, 0); 48 | 49 | // create one producer and one consumer thread 50 | pthread_create(&tid_produce, NULL, produce, NULL); 51 | pthread_create(&tid_consume, NULL, consume, NULL); 52 | 53 | // wait for the two threads 54 | pthread_join(tid_produce, NULL); 55 | pthread_join(tid_consume, NULL); 56 | 57 | // sem_close will happen automaticly when the process ends 58 | // so the next 3 sem_close call can be omited 59 | sem_close(shared.mutex); 60 | sem_close(shared.nempty); 61 | sem_close(shared.nstored); 62 | 63 | // remove the semaphores 64 | sem_unlink(SEM_MUTEX); 65 | sem_unlink(SEM_NEMPTY); 66 | sem_unlink(SEM_NSTORED); 67 | 68 | return 0; 69 | } 70 | 71 | void *produce(void *arg) 72 | { 73 | int i = 0; 74 | 75 | for (i=0; i 2 | #include 3 | #include 4 | #include "addressbook.pb.h" 5 | 6 | 7 | using namespace std; 8 | 9 | 10 | // this function fills in a Person message based on user input. 11 | void prompt_for_address(Person *person) 12 | { 13 | cout << "enter person ID number: "; 14 | int id; 15 | cin >> id; 16 | person->set_id(id); 17 | cin.ignore(256, '\n'); 18 | 19 | cout << "enter name: "; 20 | getline(cin, *person->mutable_name()); 21 | 22 | cout << "enter email address (blank for none): "; 23 | string email; 24 | getline(cin, email); 25 | if (!email.empty()) 26 | { 27 | person->set_email(email); 28 | } 29 | 30 | while (true) 31 | { 32 | cout << "enter a phone number (or leave blank to finish): "; 33 | string number; 34 | getline(cin, number); 35 | if (number.empty()) 36 | { 37 | break; 38 | } 39 | Person::PhoneNumber *phone_number = person->add_phone(); 40 | phone_number->set_number(number); 41 | 42 | cout << "is this a mobile, home, or work phone?"; 43 | string type; 44 | getline(cin, type); 45 | if ("mobile" == type) 46 | { 47 | phone_number->set_type(Person::MOBILE); 48 | } 49 | else if ("home" == type) 50 | { 51 | phone_number->set_type(Person::HOME); 52 | } 53 | else if ("work" == type) 54 | { 55 | phone_number->set_type(Person::WORK); 56 | } 57 | else 58 | { 59 | cout << "unknown phone type. using default." << endl; 60 | } 61 | } 62 | return; 63 | } 64 | 65 | // main function: reads the entire address book from a file, 66 | // add one person based on user input, then writes it back to 67 | // the same file 68 | int main(int argc, char **argv) 69 | { 70 | // verify that the version of the library that we linked against is 71 | // compatible with the version of the headers we compiled against. 72 | GOOGLE_PROTOBUF_VERIFY_VERSION; 73 | 74 | if (argc != 2) 75 | { 76 | cerr << "usage: " << argv[0] << " address_book_file" << endl; 77 | return -1; 78 | } 79 | 80 | AddressBook address_book; 81 | 82 | // read the existing address book 83 | fstream input(argv[1], ios::in | ios::binary); 84 | if (!input) 85 | { 86 | cout << argv[1] << ": File not found. Creating a new file." << endl; 87 | } 88 | else if (!address_book.ParseFromIstream(&input)) 89 | { 90 | cerr << "failed to parse address book." << endl; 91 | return -1; 92 | } 93 | 94 | // add an addres 95 | prompt_for_address(address_book.add_person()); 96 | 97 | // write the new address back to disk 98 | fstream output(argv[1], ios::out | ios::trunc | ios::binary); 99 | if (!address_book.SerializeToOstream(&output)) 100 | { 101 | cerr << "failed to write address book." << endl; 102 | return -1; 103 | } 104 | 105 | // optional: delete all global objects allocated by libprotobuf. 106 | google::protobuf::ShutdownProtobufLibrary(); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /openssl_demo/openssl_rsa_demo2.cpp: -------------------------------------------------------------------------------- 1 | // 通过命令行openssl命令来生成PEM格式公私密钥对 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //before start run this app, run the cmd below 11 | //openssl genrsa -out test.key 1024 12 | //openssl rsa -in test.key -pubout -out test_pub.key 13 | //openssl rsa -in test.key -RSAPublicKey_out -out test_pub.key 这个可以使用注释中说死活不成功那个运行成功 14 | 15 | #define OPENSSLKEY "test.key" 16 | #define PUBLICKEY "test_pub.key" 17 | 18 | char* my_encrypt(char *str, char *path_key);//加密 19 | char* my_decrypt(char *str, char *path_key);//解密 20 | 21 | int main(void) 22 | { 23 | char source[] = "i like dancing !"; 24 | char *ptr_en = NULL; 25 | char *ptr_de = NULL; 26 | 27 | printf("source is :[%lu]%s\n", strlen(source), source); 28 | ptr_en = my_encrypt(source, PUBLICKEY); 29 | printf("after encrypt:%s\n", ptr_en); 30 | 31 | ptr_de = my_decrypt(ptr_en, OPENSSLKEY); 32 | printf("after decrypt:[%lu]%s\n", strlen(ptr_de), ptr_de); 33 | 34 | if (ptr_en != NULL) 35 | { 36 | free(ptr_en); 37 | ptr_en = NULL; 38 | } 39 | if (ptr_de != NULL) 40 | { 41 | free(ptr_de); 42 | ptr_de = NULL; 43 | } 44 | return 0; 45 | } 46 | char *my_encrypt(char *str, char *path_key) 47 | { 48 | char *p_en = NULL; 49 | RSA *p_rsa = NULL; 50 | FILE *file; 51 | int flen = 0; 52 | int rsa_len = 0; 53 | 54 | file = fopen(path_key, "r"); 55 | if (NULL == file) 56 | { 57 | perror("open key file error"); 58 | return NULL; 59 | } 60 | 61 | p_rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL); 62 | // p_rsa=PEM_read_RSAPublicKey(file, NULL, NULL, NULL))==NULL) // 换成这句死活通不过,无论是否将公钥分离源文件 63 | if (NULL == p_rsa) 64 | { 65 | ERR_print_errors_fp(stdout); 66 | return NULL; 67 | } 68 | 69 | flen = strlen(str); // must < rsa_len-11 70 | rsa_len = RSA_size(p_rsa); 71 | p_en = ( char *)malloc(rsa_len+1); 72 | memset(p_en, 0, rsa_len+1); 73 | if (RSA_public_encrypt(flen, (unsigned char *)str, (unsigned char*)p_en, p_rsa, RSA_PKCS1_PADDING) < 0) 74 | { 75 | perror("pub encrypt error"); 76 | return NULL; 77 | } 78 | RSA_free(p_rsa); 79 | fclose(file); 80 | 81 | return p_en; 82 | } 83 | 84 | char *my_decrypt(char *str, char *path_key) 85 | { 86 | char *p_de = NULL; 87 | RSA *p_rsa = NULL; 88 | FILE *file; 89 | int rsa_len = 0; 90 | int flen = 0; 91 | 92 | file = fopen(path_key, "r"); 93 | if (NULL == file) 94 | { 95 | perror("open key file error"); 96 | return NULL; 97 | } 98 | 99 | p_rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL); 100 | if (NULL == p_rsa) 101 | { 102 | ERR_print_errors_fp(stdout); 103 | return NULL; 104 | } 105 | 106 | flen = strlen(str); // must < rsa_len-11 107 | rsa_len = RSA_size(p_rsa); 108 | p_de = (char *)malloc(rsa_len+1); 109 | memset(p_de, 0, rsa_len+1); 110 | int de_len = RSA_private_decrypt(flen, (unsigned char *)str, (unsigned char*)p_de, p_rsa, RSA_PKCS1_PADDING); 111 | if (de_len < 0) 112 | { 113 | perror("pri decrypt error"); 114 | return NULL; 115 | } 116 | RSA_free(p_rsa); 117 | fclose(file); 118 | return p_de; 119 | } 120 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/student_types.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.1) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "student_types.h" 8 | 9 | #include 10 | 11 | 12 | 13 | const char* Student::ascii_fingerprint = "457B6E35E5EAAA1DBF18D6B3763BD82E"; 14 | const uint8_t Student::binary_fingerprint[16] = {0x45,0x7B,0x6E,0x35,0xE5,0xEA,0xAA,0x1D,0xBF,0x18,0xD6,0xB3,0x76,0x3B,0xD8,0x2E}; 15 | 16 | uint32_t Student::read(::apache::thrift::protocol::TProtocol* iprot) { 17 | 18 | uint32_t xfer = 0; 19 | std::string fname; 20 | ::apache::thrift::protocol::TType ftype; 21 | int16_t fid; 22 | 23 | xfer += iprot->readStructBegin(fname); 24 | 25 | using ::apache::thrift::protocol::TProtocolException; 26 | 27 | 28 | while (true) 29 | { 30 | xfer += iprot->readFieldBegin(fname, ftype, fid); 31 | if (ftype == ::apache::thrift::protocol::T_STOP) { 32 | break; 33 | } 34 | switch (fid) 35 | { 36 | case 1: 37 | if (ftype == ::apache::thrift::protocol::T_I32) { 38 | xfer += iprot->readI32(this->sno); 39 | this->__isset.sno = true; 40 | } else { 41 | xfer += iprot->skip(ftype); 42 | } 43 | break; 44 | case 2: 45 | if (ftype == ::apache::thrift::protocol::T_STRING) { 46 | xfer += iprot->readString(this->sname); 47 | this->__isset.sname = true; 48 | } else { 49 | xfer += iprot->skip(ftype); 50 | } 51 | break; 52 | case 3: 53 | if (ftype == ::apache::thrift::protocol::T_BOOL) { 54 | xfer += iprot->readBool(this->ssex); 55 | this->__isset.ssex = true; 56 | } else { 57 | xfer += iprot->skip(ftype); 58 | } 59 | break; 60 | case 4: 61 | if (ftype == ::apache::thrift::protocol::T_I16) { 62 | xfer += iprot->readI16(this->sage); 63 | this->__isset.sage = true; 64 | } else { 65 | xfer += iprot->skip(ftype); 66 | } 67 | break; 68 | default: 69 | xfer += iprot->skip(ftype); 70 | break; 71 | } 72 | xfer += iprot->readFieldEnd(); 73 | } 74 | 75 | xfer += iprot->readStructEnd(); 76 | 77 | return xfer; 78 | } 79 | 80 | uint32_t Student::write(::apache::thrift::protocol::TProtocol* oprot) const { 81 | uint32_t xfer = 0; 82 | xfer += oprot->writeStructBegin("Student"); 83 | 84 | xfer += oprot->writeFieldBegin("sno", ::apache::thrift::protocol::T_I32, 1); 85 | xfer += oprot->writeI32(this->sno); 86 | xfer += oprot->writeFieldEnd(); 87 | 88 | xfer += oprot->writeFieldBegin("sname", ::apache::thrift::protocol::T_STRING, 2); 89 | xfer += oprot->writeString(this->sname); 90 | xfer += oprot->writeFieldEnd(); 91 | 92 | xfer += oprot->writeFieldBegin("ssex", ::apache::thrift::protocol::T_BOOL, 3); 93 | xfer += oprot->writeBool(this->ssex); 94 | xfer += oprot->writeFieldEnd(); 95 | 96 | xfer += oprot->writeFieldBegin("sage", ::apache::thrift::protocol::T_I16, 4); 97 | xfer += oprot->writeI16(this->sage); 98 | xfer += oprot->writeFieldEnd(); 99 | 100 | xfer += oprot->writeFieldStop(); 101 | xfer += oprot->writeStructEnd(); 102 | return xfer; 103 | } 104 | 105 | void swap(Student &a, Student &b) { 106 | using ::std::swap; 107 | swap(a.sno, b.sno); 108 | swap(a.sname, b.sname); 109 | swap(a.ssex, b.ssex); 110 | swap(a.sage, b.sage); 111 | swap(a.__isset, b.__isset); 112 | } 113 | 114 | 115 | -------------------------------------------------------------------------------- /network/strservselect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #define MAXLINE 1024 13 | #define SERV_PORT 9877 14 | #define LISTENQ 1024 15 | 16 | #define min(a,b) ((a) < (b) ? (a) : (b)) 17 | #define max(a,b) ((a) > (b) ? (a) : (b)) 18 | 19 | int main(int argc, char **argv) 20 | { 21 | int i, maxi, maxfd, listenfd, connfd, sockfd; 22 | int nready, client[FD_SETSIZE]; 23 | ssize_t n; 24 | fd_set rset, allset;; 25 | char buf[MAXLINE]; 26 | socklen_t clilen; 27 | struct sockaddr_in cliaddr, servaddr; 28 | int ret; 29 | 30 | listenfd = socket(AF_INET, SOCK_STREAM, 0); 31 | assert(listenfd > 0); 32 | 33 | int32_t reuse = 1; 34 | setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 35 | 36 | bzero(&servaddr, sizeof(servaddr)); 37 | servaddr.sin_family = AF_INET; 38 | servaddr.sin_port = htons(SERV_PORT); 39 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 40 | 41 | ret = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 42 | assert(ret != -1); 43 | 44 | ret = listen(listenfd, LISTENQ); 45 | assert(ret != -1); 46 | 47 | maxfd = listenfd; 48 | maxi = -1; 49 | for (i=0; i maxfd) 85 | { 86 | maxfd = connfd; 87 | } 88 | 89 | if (i > maxi) 90 | { 91 | maxi = i; //max index in client array 92 | } 93 | 94 | if (--nready <= 0) 95 | { 96 | continue; //no more readable descriptors 97 | } 98 | } 99 | 100 | while (1) //check all clients for data 101 | { 102 | if ((sockfd = client[i]) < 0) 103 | { 104 | continue; 105 | } 106 | 107 | if (FD_ISSET(sockfd, &rset)) 108 | { 109 | if ((n = recv(sockfd, buf, sizeof(buf), 0)) == 0) 110 | { 111 | //connection closed by client 112 | printf("recv 0\n"); 113 | close(sockfd); 114 | FD_CLR(sockfd, &allset); 115 | client[i] = -1; 116 | } 117 | else 118 | { 119 | printf("recv %d\n", n); 120 | send(sockfd, buf, n, 0); 121 | } 122 | 123 | if (--nready <= 0) 124 | { 125 | printf("no more readable descriptors\n"); 126 | break; //no more readable descriptors 127 | } 128 | } 129 | } 130 | } 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /pthread/pthread_condvar.c: -------------------------------------------------------------------------------- 1 | /* 2 | Example code for using Pthreads condition variables. 3 | The main thread creates 3 threads. Two of them increment a "count" variable, 4 | while the 3rd thread watches the value of "count". 5 | When "count" reaches a predefined limit, the waiting thread is signaled by one 6 | of the incrementing threads. The waiting thread "awakens" and then modifies the 7 | count. The program continues until the incrementing threads reach TCOUNT. The 8 | main thread prints out the final value of count. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define NUM_THREADS 3 16 | #define TCOUNT 10 17 | #define COUNT_LIMIT 12 18 | 19 | int count = 0; 20 | pthread_mutex_t count_mutex; 21 | pthread_cond_t count_threshold_cv; 22 | 23 | void *inc_count(void *t) 24 | { 25 | int i; 26 | long my_id = (long)t; 27 | 28 | for (i=0; i 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | const int MSG_LEN = 128+1; 11 | const char *PUBKEY_FILE = "public.rsa"; 12 | const char *PRIKEY_FILE = "private.rsa"; 13 | 14 | //生成RSA公钥和私钥文件 15 | int createRSAPEM() 16 | { 17 | int ret = 0; 18 | BIO *bpub = NULL; 19 | BIO *bpri = NULL; 20 | 21 | bpub = BIO_new_file(PUBKEY_FILE, "w"); 22 | if (!bpub) 23 | { 24 | printf("failed to create public bio file\n"); 25 | } 26 | 27 | bpri = BIO_new_file(PRIKEY_FILE, "w"); 28 | if (!bpri) 29 | { 30 | printf("failed to create private bio file\n"); 31 | } 32 | 33 | if (!bpub || !bpri) 34 | { 35 | goto EXIT; 36 | } 37 | 38 | RSA *pRSA; 39 | pRSA = RSA_generate_key( 1024, RSA_F4, NULL, NULL); 40 | if (pRSA != NULL) 41 | { 42 | if (!PEM_write_bio_RSAPublicKey(bpub, pRSA))//PEM_write_bio_RSA_PUBKEY 43 | { 44 | printf("PEM_write_bio_RSAPublicKey: failed\n"); 45 | goto EXIT; 46 | } 47 | 48 | //if (!PEM_write_bio_RSAPrivateKey(bpri, pRSA, EVP_aes_256_cbc(), NULL, 0, NULL, NULL))//暂时设置密码 49 | if (!PEM_write_bio_RSAPrivateKey(bpri, pRSA, NULL, NULL, 0, NULL, NULL)) 50 | { 51 | printf("PEM_write_bio_PrivateKey: failed\n"); 52 | goto EXIT; 53 | } 54 | ret =1; 55 | } 56 | EXIT: 57 | if (bpub) 58 | { 59 | BIO_free(bpub); 60 | } 61 | if (bpri) 62 | { 63 | BIO_free(bpri); 64 | } 65 | if (pRSA) 66 | { 67 | RSA_free(pRSA); 68 | } 69 | 70 | return ret; 71 | } 72 | 73 | //使用公钥加密 74 | int rsa_encrypt(char *in, const char *key_path, char* out) 75 | { 76 | RSA *p_rsa; 77 | FILE *file; 78 | int rsa_len; 79 | if ((file=fopen(key_path, "r"))==NULL) 80 | { 81 | perror("open key file error"); 82 | return 0; 83 | } 84 | 85 | //if ((p_rsa=PEM_read_RSA_PUBKEY(file, NULL, &ccbb, NULL))==NULL){ 86 | if ((p_rsa=PEM_read_RSAPublicKey(file, NULL, NULL, NULL))==NULL){ 87 | ERR_print_errors_fp(stdout); 88 | return 0; 89 | } 90 | rsa_len=RSA_size(p_rsa); 91 | if (RSA_public_encrypt(rsa_len, (unsigned char*)in, (unsigned char*)out, p_rsa, RSA_NO_PADDING)<0) 92 | { 93 | return 0; 94 | } 95 | RSA_free(p_rsa); 96 | fclose(file); 97 | return 1; 98 | } 99 | 100 | //使用私钥解密 101 | int rsa_decrypt(char *in, const char *key_path, char* out) 102 | { 103 | RSA *p_rsa; 104 | FILE *file; 105 | int rsa_len; 106 | if ((file=fopen(key_path, "r"))==NULL) 107 | { 108 | perror("open key file error"); 109 | return 0; 110 | } 111 | 112 | if ((p_rsa=PEM_read_RSAPrivateKey(file, NULL, NULL, NULL))==NULL) 113 | { 114 | ERR_print_errors_fp(stdout); 115 | return 0; 116 | } 117 | 118 | rsa_len=RSA_size(p_rsa); 119 | if (RSA_private_decrypt(rsa_len, (unsigned char*)in, (unsigned char*)out, p_rsa, RSA_NO_PADDING)<0) 120 | { 121 | return 0; 122 | } 123 | RSA_free(p_rsa); 124 | fclose(file); 125 | return 1; 126 | } 127 | 128 | int main(int argc, char**argv) 129 | { 130 | char clearString[MSG_LEN] = "this is the data to be encrypted"; 131 | char encryptString[MSG_LEN] = {};; 132 | char decryptString[MSG_LEN] = {}; 133 | 134 | createRSAPEM(); 135 | 136 | if (!rsa_encrypt(clearString, PUBKEY_FILE, encryptString)) 137 | { 138 | printf("encrypt error\n"); 139 | return -1; 140 | } 141 | 142 | if (!rsa_decrypt(encryptString, PRIKEY_FILE, decryptString)) 143 | { 144 | printf("decrypt error\n"); 145 | return -1; 146 | } 147 | 148 | printf("\n"); 149 | printf("before encrypt, the plaintext is:\n[%lu]:%s\n", strlen(clearString), clearString); 150 | printf("after encrypt, the encrypted text len is:%s\n", encryptString); 151 | printf("after decrypt, the decrypted text is:\n[%lu]:%s\n", strlen(decryptString), decryptString); 152 | printf("\n"); 153 | 154 | if (memcmp(clearString, decryptString, MSG_LEN) == 0) 155 | { 156 | printf("Yes, it worked!\n"); 157 | } 158 | else 159 | { 160 | printf("Oh, no!\n"); 161 | } 162 | 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /utility/parse_lc_rules.c: -------------------------------------------------------------------------------- 1 | /*================================================================ 2 | * Copyright (C) 2014 All rights reserved. 3 | * 4 | * FileName:parse_lc_rules.c 5 | * Author :Carl 6 | * Creat Date:2014.03.13 7 | * Description: 8 | * 9 | ================================================================*/ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef enum tagLC_RULES 17 | { 18 | AVAILABLE, 19 | UNAVAILABLE 20 | } LC_RULE; 21 | 22 | typedef enum tagLC_PROTOCOL 23 | { 24 | UNKOWN, 25 | CMD1, 26 | CMD2, 27 | CMD3, 28 | MAX_PROTOCOL 29 | } LC_PROTOCOL; 30 | 31 | static g_lc_rules[MAX_PROTOCOL] = {}; 32 | 33 | char *rules_example = "getsysinfo=no\r\ninner_protocol=yes\r\n"; 34 | 35 | void lc_set_cmd_rules(char *rule_buf); 36 | LC_RULE lc_check_rules_type(char *rule); 37 | LC_PROTOCOL lc_check_protocol_type(char **protocol); 38 | void lc_set_cmd_rule(LC_PROTOCOL protocol, LC_RULE rule); 39 | LC_RULE lc_get_cmd_rule(LC_PROTOCOL protocol); 40 | void lc_set_global_ctrl(char *rule); 41 | static int g_lc_net_filter_method = 0; 42 | 43 | 44 | int main(int argc ,char **argv) 45 | { 46 | 47 | lc_set_cmd_rules(rules_example); 48 | printf("\n"); 49 | int i = 0; 50 | for (i=0; i strlen(sep1) && (pstart = pend + strlen(sep1))); 113 | } 114 | 115 | void lc_set_cmd_rule(LC_PROTOCOL protocol, LC_RULE rule) 116 | { 117 | g_lc_rules[protocol] = rule; 118 | } 119 | 120 | LC_RULE lc_get_cmd_rule(LC_PROTOCOL protocol) 121 | { 122 | return g_lc_rules[protocol]; 123 | } 124 | 125 | LC_RULE lc_check_rules_type(char *rule) 126 | { 127 | if (strcasecmp(rule, "yes") == 0) 128 | return AVAILABLE; 129 | else if (strcasecmp(rule, "no") == 0) 130 | return UNAVAILABLE; 131 | } 132 | 133 | LC_PROTOCOL lc_check_protocol_type(char **protocol) 134 | { 135 | if (strcasecmp(*protocol, "getsysinfo") == 0) 136 | return CMD1; 137 | else if (strcasecmp(*protocol, "inner_protocol") == 0) 138 | return CMD2; 139 | else 140 | return UNKOWN; 141 | } 142 | 143 | 144 | void lc_set_global_ctrl(char *rule) 145 | { 146 | if (0 == strcmp(rule, "all")) 147 | { 148 | g_lc_net_filter_method = 1; 149 | } 150 | else if (0 == strcmp(rule, "lan")) 151 | { 152 | g_lc_net_filter_method = 2; 153 | } 154 | else if (0 == strcmp(rule, "localhost")) 155 | { 156 | g_lc_net_filter_method = 3; 157 | } 158 | else 159 | { 160 | g_lc_net_filter_method = 4; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /ipc/mutex_cond/README.md: -------------------------------------------------------------------------------- 1 | 互斥锁和条件变量 2 | === 3 | 4 | 互斥锁和条件变量总是可用来同步一个进程内的各个线程。但是如果一个互斥锁或条件变量是 5 | 存放在多个进程间共享的某个内存区内,那么它还可以被用来同步这几个进程。 6 | 7 | 互斥锁指代相互排斥,用于保护临界区,以保证任何时刻**只有一个线程/进程**在执行 8 | 其中的代码。保护一个临界区的代码的通常轮廓大体如下: 9 | 10 | ```cpp 11 | lock_the_mutex(...) 12 | 操作临界区 13 | unlock_the_mutex(...) 14 | ``` 15 | 16 | **互斥锁的初始化**: 17 | 18 | 1. 静态分配。 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 19 | 2. 动态分配。 在运行之时通过调用pthread_mutex_init函数来初始化。 20 | 21 | **API** 22 | 23 | ```cpp 24 | #include 25 | 26 | int pthread_mutex_lock(pthread_mutex_t *mptr); // block 27 | int pthread_mutex_trylock(pthread_mutex_t *mptr); // unblock 28 | int pthread_mutex_unlock(pthread_mutex_t *mptr); 29 | 返回: 成功返回0,失败返回Exxx错误码 30 | 31 | 如果尝试给一个已由另外某个线程锁住的互斥锁上锁,那么pthread_mutex_lock会阻塞到该 32 | 互斥锁被解锁为止,pthread_mutex_trylock是对应的非阻塞函数,如果该互斥锁已锁住, 33 | 它就返回一个EBUSY错误 34 | 35 | ``` 36 | 37 | 互斥锁是协作性锁。**由coder来保证**操作临界区之前获取对应互斥锁。 38 | 39 | * prodcons_mutex.c 使用互斥锁的producer-consumer示例 40 | 41 | ##条件变量 42 | 43 | 互斥锁用于上锁,条件变量用于等待. 44 | 45 | 条件变量类型为:pthread_cond_t 46 | 47 | ```cpp 48 | int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr); 49 | int pthread_cond_signal(pthread_cond_t *cptr); 50 | 返回: 成功返回0,失败返回Exxx错误码 51 | 52 | ``` 53 | 54 | 每个条件变量总是有一个互斥锁与之关联 55 | 56 | pthread_cond_wait **会原子地**执行2个动作 57 | 58 | 1. 给互斥锁mptr解锁 59 | 2. 把调用线程投入睡眠,直到另外某个线程就本条件变量调用pthread_cond_signal, 60 | pthread_cond_wait返回前重新给mptr上锁 61 | 62 | **给条件变量发送信号的代码:** 63 | 64 | ```cpp 65 | struct 66 | { 67 | pthread_mutex_t mutex; 68 | pthread_cond_t cond; 69 | // vars 70 | } var = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, ...}; 71 | 72 | pthread_mutex_lock(&var.mutex); 73 | 设置条件为真 74 | pthread_cond_signal(&var.cond); 75 | pthread_mutex_unlock(&var.mutex); 76 | 77 | 调用pthread_cond_signal的线程不必是与之关联的互斥锁的当前属主。但是如果需要可预见的 78 | 调度行为,那么调用pthread_cond_signal的线程必须锁住该互斥锁 79 | 80 | ``` 81 | 82 | 83 | **测试条件并进入睡眠以等待该条件变为真的代码:** 84 | 85 | ```cpp 86 | pthread_mutex_lock(&var.mutex); 87 | while (条件为假) 88 | pthread_cond_wait(&var.cond, &var.mutex); 89 | 修改条件 90 | pthread_mutex_unlock(&var.mutex); 91 | 92 | ``` 93 | 94 | * prodcons_mutex_cond.c 使用条件变量的producer-consumer示例 95 | 96 | 97 | ###条件变量的定时等待和广播 98 | 99 | ```cpp 100 | #include 101 | 102 | int pthread_cond_broadcast(pthread_cond_t *cptr); 103 | int pthread_cond_timewait(pthread_cond_t *cptr, pthread_mutex_t *mptr, const struct timespec *abstime); 104 | 返回: 成功返回0,失败返回Exxx错误码 105 | 106 | pthread_cond_timewait 超时返回ETIMEOUT错误 107 | 108 | struct timespec 109 | { 110 | time_t tv_sec; // seconds 111 | long tv_nsec; // nanosecondes 112 | }; 113 | abstime是UTC时间,而不是时间差 114 | ``` 115 | 116 | ##互斥锁和条件变量的属性 117 | 118 | ```cpp 119 | #include 120 | 121 | int pthread_mutex_init(pthread_mutex_t *mptr, const pthread_mutexattr_t *attr); 122 | int pthread_mutex_destory(pthread_mutex_t *mptr); 123 | int pthread_cond_init(pthread_cond_t *cptr, const pthread_condattr_t *attr); 124 | int pthread_cond_destroy(pthread_cond_t *cptr); 125 | int pthread_mutexattr_init(pthread_mutexattr_t *attr); 126 | int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); 127 | int pthread_condattr_init(pthread_condattr_t *attr); 128 | int pthread_condattr_destroy(pthread_condattr_t *attr); 129 | 返回: 成功返回0,失败返回Exxx错误码 130 | 131 | ``` 132 | 133 | 一旦某个互斥锁属性对象或者某个条件变量属性对象已被初始化,就通过调用不同函数启用或 134 | 禁止特定的特性。例如,指定互斥锁或条件变量在不同进程间共享,而不是只在单个进程内的 135 | 不同线程间共享 136 | 137 | ```cpp 138 | #include 139 | 140 | int pthread_mutexattr_getpshared(const pthread_mutexattr_t *ptr, int *valptr); 141 | int pthread_mutexattr_setpshared(const pthread_mutexattr_t *ptr, int val); 142 | int pthread_condattr_getpshared(const pthread_condattr_t *ptr, int *valptr); 143 | int pthread_condattr_setpshared(const pthread_condattr_t *ptr, int val); 144 | 返回: 成功返回0,失败返回Exxx错误码 145 | 146 | ``` 147 | 148 | 这个特性只在 19 | 20 | void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); 21 | 返回: 成功返回被映射区的起始地址, 失败返回MAP_FAILED 22 | 23 | addr 可以指定描述符fd应被映射到的进程内空间的起始地址. 它通常被设为NULL, 这 24 | 样告诉内核自己去选择起始地址 25 | 26 | len 映射到调用进程地址空间中的字节数, 它从被映射文件开头起第offset个字节处 27 | 开始算. 通常被设置为0 28 | 29 | prot 指定内存映射区的保护, 常见值是 PROT_READ | PROT_WRITE 30 | prot 说明 31 | PROT_READ 数据可读 32 | PROT_WRITE 数据可写 33 | PROT_EXEC 数据可执行 34 | PROT_NONE 数据不可访问 35 | 36 | flags MAP_SHARED或MAP_PRIVATE这两个标志必须指定一个, 并有选择地 | MAP_FIXED. 37 | MAP_PRIVATE 调用进程对被映射数据所做的修改只对本进程可见, 而不改变底层 38 | 支撑对象 39 | MAP_SHARED 调用进程对被映射数据所做的修改对于共享该对象的所有进程都可 40 | 见, 而且确实改变了其底层支撑对象 41 | 42 | Flags 说明 43 | MAP_PRIVATE 变动是私自的 44 | MAP_SHARED 变动是共享的 45 | MAP_FIXED 准确的解释addr参数 46 | 47 | 从移植性上考虑, MAP_FIXED不应被指定. 可移植性的代码应该把addr置为NULL, 48 | 不指定MAP_FIXED 49 | 50 | 父子进程之间共享内存区的方法之一: 父进程在调用fork之前先指定MAP_SHARED调用mmap. 51 | Posix.1保证父进程中的内存映射关系存留到子进程中. 52 | 53 | int munmap(void *addr, size_t len); 54 | 返回: 成功返回0, 失败返回-1 55 | 56 | 从某个进程的地址空间删除一个映射关系. munmap后再访问这些地址将会导致想调用进程 57 | 产生一个SIGSEGV信号 58 | 59 | 如果被映射区是使用MAP_PRIVATE标志映射的, 那么调用进程对它所做的变动都会被丢弃掉. 60 | 61 | addr mmap返回的地址 62 | len 映射区的大小 63 | 64 | int msync(void *addr, size_t len, int flags); 65 | 返回: 成功返回0, 失败返回-1 66 | 67 | 内核的虚拟内存算法保持内存映射文件(一般在硬盘上)与内存映射区(在内存中)的同步, 68 | 前提是它是一个MAP_SHARED内存区. 如果我们修改了处于内存映射到某个文件的内存区中 69 | 某个位置的内容, 那么内核将在稍后某个时刻相应的更新文件. 然而有时候希望确信硬盘 70 | 上的文件内容与内存映射区中的内容一致, 这就需要调用msync来执行这种同步 71 | 72 | addr和len通常指代内存中的整个内存映射区, 不过也可以指定该内存区的一个子集. 73 | flags参数: MS_ASYNC和MS_SYNC必须指定一个, 但不能同时指定 74 | - MS_ASYNC 执行异步写, 一旦写操作由内核排入队列, 立即返回 75 | - MS_SYNC 执行同步写, ........................, 等到写操作完成后才返回 76 | - MS_INVALIDATE 使高速缓存的数据失效. 指定了该flag, 那么与其最终副本不一致的文 77 | 件数据的所有内存中副本都失效, 后续的引用将从文件中取得数据. 78 | 79 | Posix还定义了处理内存管理的4个额外函数 80 | - mlockall会使调用进程的整个内存空间常驻内存. munlockall则撤销这种锁定 81 | - mlcok会是调用进程地址空间的某个指定范围常驻内存, 该函数的参数指定了这个范围的 82 | 起始地址以及从该地址算起的字节数. munlock则撤销某个指定内存区的锁定. 83 | 84 | ``` 85 | 86 | 使用mmap的好处: 87 | 88 | 使用内存映射文件所得到的奇妙特性是, 所有的I/O都在内核的掩盖下完成, 我们只需编 89 | 写存取内存映射区中各个值的代码. 我们决不调用read, write, lseek, 把显示的文件 90 | I/O操作变换成存取内存单元, 这样可以简化我们的代码, 有时候还能改善性能 91 | 92 | mmap的另一个用途是在无亲缘关系的进程间提供共享内存区(需指定MAP_SHARED标志).这 93 | 种情形下, 所映射文件的实际内容成了被共享内存区的初始内容, 而且这些进程对该共享 94 | 内存区所做的任何变动都复制回所映射的文件(以提供随文件系统的持续性). 95 | 96 | - count01.c 父子进程给共享内存区的一个计数器加1, 使用有名信号量 97 | - count02.c 父子进程给共享内存区的一个计数器加1, 使用基于内存的信号量 98 | 99 | 内存映射一个普通文件时, 内存映射区的大小(mmap的第二个参数)通常等于该文件的大小. 100 | 但是文件大小和内存映射区大小可以不同. 我们总是能够访问在当前文件大小以内又在内 101 | 存映射区以内的那些字节. 102 | 103 | - SIGBUS 内存映射区大小 > 文件大小, 访问了超出文件大小的位置但是未超出内存映射区 104 | - SIGSEGV 越界访问内存映射区 105 | 106 | 107 | ###Posix共享内存区 108 | --- 109 | 110 | 两者无亲缘关系进程间共享内存区的方法 111 | 112 | 1. 内存映射文件. 由open函数打开, 由mmap函数把所得到的描述符映射到当前进程地址空 113 | 间中的一个文件 114 | 2. 共享内存区对象. 由shm_open打开一个Posix.1 IPC名字, 所返回的描述符由mmap函数 115 | 映射到当前进程地址空间 116 | 117 | ```cpp 118 | #include 119 | 120 | int shm_open(const char *name, int oflag, mode_t mode); 121 | 返回: 成功返回非负描述符, 失败返回-1 122 | 123 | oflag 必须含有O_RDONLY或O_RDWR之一, 还可以有O_CREAT, O_EXCL. 如果 O_RDWR | O_TRUNC, 124 | 而且所需的共享内存区对象已经存在, 那么它将被截断为0长度. 125 | mode 指定权限位, 在O_CREAT时必须指定mode, 未指定O_CREAT时可以mode设为0 126 | 127 | int shm_unlink(const char *name); 128 | 返回: 成功返回0, 失败返回-1 129 | 130 | shm_unlink删除一个共享内存区对象的名字. 跟所有其他unlink函数(删除文件系统中一个路径名 131 | 的unlink, 删除一个Posix消息队列的mq_unlink, 以及删除一个Posix有名信号量的sem_unlink) 132 | 一样, 删除一个名字不会影响对于底层支撑对象的现有引用, 知道对于该对象的引用全部关闭为 133 | 止. 删除一个名字仅仅防止后续的open, mq_open或sem_open调用取得成功. 134 | 135 | #include 136 | int ftruncate(int fd, off_t length); 137 | 返回: 成功返回0, 失败返回-1 138 | 139 | 调用ftruncate来指定新创建的共享内存区对象的大小, 或者修改已存在的对象的大小. 140 | 141 | - 对于普通文件: 如果该文件大小大于length, 额外的数据就被丢弃掉, 如果该文件的大小小于 142 | length, 那么该文件是否修改以及其大小是否增长是未定义的. 143 | 实际上对于一个普通文件, 把它的大小扩展到length字节的可移植办法是:先lseek到偏移为 144 | length-1处, 然后write 1个字节的数据 145 | - 对于共享内存区对象: 把该对象的大小设置成length字节. 146 | 147 | #include 148 | #include 149 | int fstat(int fd, struct stat *buf); 150 | 返回: 成功返回0, 失败返回-1 151 | 152 | struct stat有12个或以上的成员, 但是当fd指代一个共享内存区对象时, 只有4个成员含有信息 153 | struct stat 154 | { 155 | ... 156 | mode_t st_mode; // mode: S_I{RW}{USR, GRP, OTH} 157 | uid_t st_uid; // user id of owner 158 | gid_t st_gid; // group id of owner 159 | off_t st_size; // size in bytes 160 | ... 161 | }; 162 | 163 | ``` 164 | 165 | - shmcreate.c 创建一个具有指定大小的Posix共享内存区对象 166 | - shmunlink.c 删除一个共享内存区对象的名字 167 | - shmwrite.c 打开一个共享内存区对象, 填写一个数据模式 168 | - shmread.c 打开一个共享内存区对象, 验证其数据模式 169 | 170 | 同一个共享内存区对象内存映射到不同进程的地址空间时, 起始地址可以不同. 171 | 172 | - count03_server.c 创建并初始化共享内存区和信号量的程序 173 | - count03_client.c 给存放在共享内存区中的一个计数器加1, 测试的时候可以启动多个client 174 | 来观察效果 175 | 176 | - cosumer.c 从共享内存区中取得并输出消息 177 | - producer.c 在共享内存区存放消息 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /openssl_demo/openssl_rsa_demo1.cpp: -------------------------------------------------------------------------------- 1 | // 在代码中生成公私密钥对 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | const int MAX_RSA_KEY_LENGTH = 512; //密钥的最大长度是512字节 9 | 10 | unsigned char *g_pub_key = NULL; 11 | unsigned char *g_pri_key = NULL; 12 | int g_pub_key_len = 0; 13 | int g_pri_key_len = 0; 14 | 15 | using namespace std; 16 | 17 | int gen_rsakeypair(void) 18 | { 19 | RSA *rsa = NULL; 20 | unsigned char *pt = NULL; 21 | unsigned char *pt2 = NULL; 22 | 23 | //生成RSA密钥对: 24 | rsa = RSA_new(); 25 | rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); 26 | 27 | g_pub_key_len = i2d_RSAPublicKey(rsa, NULL); // get pubkey size 28 | g_pub_key = (unsigned char *)malloc(g_pub_key_len+1); // alloc memory for g_pub_key 29 | memset(g_pub_key, 0, g_pub_key_len+1); 30 | pt = g_pub_key; // must use p, as the para will change 31 | g_pub_key_len = i2d_RSAPublicKey(rsa, &pt); // 提取公钥大小, 并将公钥放入buffer中 32 | 33 | g_pri_key_len = i2d_RSAPrivateKey(rsa, NULL); // get prikey size 34 | g_pri_key = (unsigned char *)malloc(g_pri_key_len+1); 35 | memset(g_pri_key, 0, g_pri_key_len+1); 36 | pt2 = g_pri_key; // 这里如果复用上面的pt指针,在下一行就会改变g_pub_key_len的值,不知道为什么 37 | g_pri_key_len = i2d_RSAPrivateKey(rsa, &pt2); 38 | 39 | if(rsa != NULL) 40 | { 41 | RSA_free(rsa); 42 | rsa = NULL; 43 | } 44 | 45 | return 0; 46 | } 47 | 48 | //取得RSA格式的私钥: 49 | int get_prikey(const unsigned char *pri_key, unsigned long pri_key_len, RSA **pri_rsa) 50 | { 51 | const unsigned char *pt = pri_key; 52 | *pri_rsa = d2i_RSAPrivateKey(NULL, &pt, pri_key_len); 53 | if (NULL == pri_rsa) 54 | { 55 | cout << "pri_rsa == NULL!" << endl; 56 | return 0x22; 57 | } 58 | 59 | // 打印私钥信息,实际上,私钥含有p、q等,所以可以推导出公钥 60 | printf("\n"); 61 | printf("pri_key info:\n"); 62 | printf("p(%d bytes):%s\n",BN_num_bytes((*pri_rsa)->p), BN_bn2hex((*pri_rsa)->p)); 63 | printf("q(%d bytes):%s\n",BN_num_bytes((*pri_rsa)->q), BN_bn2hex((*pri_rsa)->q)); 64 | printf("d(%d bytes):%s\n",BN_num_bytes((*pri_rsa)->d), BN_bn2hex((*pri_rsa)->d)); 65 | printf("\n"); 66 | return 0; 67 | } 68 | 69 | //取得RSA格式的公钥: 70 | int get_pubkey(const unsigned char *pub_key,unsigned long pub_keylen, RSA **pub_rsa) 71 | { 72 | const unsigned char *pt = pub_key; 73 | *pub_rsa = d2i_RSAPublicKey(NULL, &pt, pub_keylen); 74 | if (NULL == pub_rsa) 75 | { 76 | cout << "pub_rsa == NULL!" << endl; 77 | return 0x31; 78 | } 79 | 80 | //打印公钥对应的信息,公钥包含N和e,而私钥拥N和d 81 | //实际上,私钥含有p、q等,所以可以推导出公钥 82 | printf("\n"); 83 | printf("pub_key info:\n"); 84 | printf("N(%d bytes):%s\n",BN_num_bytes((*pub_rsa)->n), BN_bn2hex((*pub_rsa)->n)); 85 | printf("e(%d bytes):%s\n",BN_num_bytes((*pub_rsa)->e), BN_bn2hex((*pub_rsa)->e)); 86 | printf("\n"); 87 | return 0; 88 | } 89 | 90 | //公钥加密 91 | int enc_by_rsapubkey(RSA *rsa, unsigned char *plain_text, unsigned long plain_text_len, 92 | unsigned char *encrypted_text, unsigned long *encrypted_text_len) 93 | { 94 | *encrypted_text_len = RSA_public_encrypt(plain_text_len, plain_text, encrypted_text, rsa, RSA_PKCS1_PADDING); 95 | return *encrypted_text_len; 96 | } 97 | 98 | //私钥解密: 99 | int dec_by_rsaprikey(RSA *rsa, unsigned char *encrypted_text, unsigned long encrypted_text_len, 100 | unsigned char *plain_text, unsigned long *plain_text_len) 101 | { 102 | *plain_text_len = RSA_private_decrypt(encrypted_text_len, encrypted_text, plain_text, rsa, RSA_PKCS1_PADDING); 103 | return *plain_text_len; 104 | } 105 | 106 | 107 | int main(int argc, char **argv) 108 | { 109 | unsigned char plain_text[] = "this is the data to be encrypted"; 110 | unsigned char encrypted_text[512] = {0}; 111 | unsigned char decrypted_text[512] = {0}; 112 | unsigned long encrypted_len = 0; 113 | unsigned long decrypted_len = 0; 114 | 115 | gen_rsakeypair(); 116 | 117 | RSA *p_rsa_pubkey = NULL; 118 | p_rsa_pubkey = RSA_new(); 119 | 120 | get_pubkey(g_pub_key, g_pub_key_len, &p_rsa_pubkey); 121 | //公钥加密: 122 | enc_by_rsapubkey(p_rsa_pubkey, plain_text, sizeof(plain_text), encrypted_text, &encrypted_len); 123 | if(p_rsa_pubkey != NULL) 124 | { 125 | RSA_free(p_rsa_pubkey); 126 | p_rsa_pubkey = NULL; 127 | } 128 | 129 | RSA *p_rsa_prikey = NULL; 130 | p_rsa_prikey = RSA_new(); 131 | 132 | get_prikey(g_pri_key, g_pri_key_len, &p_rsa_prikey); 133 | //私钥解密: 134 | dec_by_rsaprikey(p_rsa_prikey, encrypted_text, encrypted_len, decrypted_text, &decrypted_len); 135 | if(p_rsa_prikey != NULL) 136 | { 137 | RSA_free(p_rsa_prikey); 138 | p_rsa_prikey = NULL; 139 | } 140 | 141 | //数据对比: 142 | printf("\n"); 143 | printf("before encrypt, the data is:\nplain_text[%lu]: %s\n", sizeof(plain_text), plain_text); 144 | printf("\n"); 145 | printf("after encrypt, the data len is:%lu\n", encrypted_len); 146 | printf("after decrypt, the data is:\ndecrypted_text[%lu]:%s\n", decrypted_len, decrypted_text); 147 | printf("\n"); 148 | if(0 == memcmp(plain_text, decrypted_text, decrypted_len)) 149 | { 150 | cout << "Yes, it worked!" << endl; 151 | } 152 | else 153 | { 154 | cout << "Oh, no!" << endl; 155 | } 156 | 157 | if (g_pub_key != NULL) 158 | { 159 | free(g_pub_key); 160 | g_pub_key = NULL; 161 | } 162 | if (g_pri_key != NULL) 163 | { 164 | free(g_pri_key); 165 | g_pri_key = NULL; 166 | } 167 | 168 | return 0; 169 | } 170 | -------------------------------------------------------------------------------- /ipc/posix_semaphore/README.md: -------------------------------------------------------------------------------- 1 | Posix信号量 2 | === 3 | 4 | #####信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。 5 | 6 | * Posix有名信号量: 使用Posix IPC名字标识,可用于进程或线程间的同步。 7 | * Posix基于内存的信号量: 存放在共享内存中,可用于进程或线程间的同步。 8 | * System V信号量: 在内核中维护,可用于进程或线程间的同步。 9 | 10 | **信号量的值是随内核持续的** 11 | 12 | 13 | #####一个进程可以在某个某个信号量上执行的三种操作 14 | 15 | 1. create一个信号量。这还要求调用者指定初始值,对于二值信号量来说,它通常是1,但也可 16 | 以是0. 17 | 2. wait一个信号量。该操作会测试这个信号量的值,如果其值<=0,那就等待(阻塞),一旦其 18 | 值变为>0,就将它减1. 19 | 20 | ```cpp 21 | while (semaphore_value <= 0) 22 | ; // wait; block the thread or process 23 | semaphore--; 24 | // now we have the semaphore 25 | ``` 26 | **注意:**while语句中测试该信号量的值和其后将它减1(如果该值大于0),这两个步骤必须是原子的 27 | 28 | 3. post一个信号量。该操作将信号量的值加1,`semaphore_value++` 29 | 30 | #####信号量、互斥锁、条件变量的差异 31 | 32 | 1. 互斥锁必须总是由给它上锁的线程解锁,信号量的post却不必由执行过它的wait操作的同一线程执行。 33 | 2. 互斥锁要么被锁住,要么被解开(二值状态,类似于二值信号量)。 34 | 3. 既然信号量有一个与之关联的状态(它的计数值),那么信号量的post操作总是被记住。然而当向一 35 | 个条件变量发送信号时,如果没有线程等待在该条件变量上,那么该信号将丢失。 36 | 4. 当持有某个**信号量**的进程没有释放它就终止时,**内核并不给该信号量解锁**。而当持有某 37 | 个**记录锁**的进程没有释放它就终止时,**内核自动地释放它** 38 | 5. 在各种各样的同步技巧(互斥锁、条件变量、读写锁、信号量)中,能够从信号处理程序中安全调 39 | 用的唯一函数是`sem_post` 40 | 41 | **每种同步方式都有各自的适用场景。互斥锁是为上锁而优化的,条件变量是为等待而优化的,信号 42 | 量既可用于上锁,也可用于等待,因而可能导致更多的开销和更高的复杂性** 43 | 44 | 45 | #####Posix有名信号量 46 | 47 | 48 | ```cpp 49 | #include 50 | 51 | sem_t *sem_open(const char *name, int oflag, ... /*mode_t mode, usigned int value*/) 52 | 返回:成功返回指向信号量的指针,出错返回SEM_FAILED 53 | 54 | sem_open创建一个新的有名信号量或打开一个已存在的有名信号量。有名信号量总是既可用于线程间的 55 | 同步,又可用于进程间的同步 56 | 57 | - oflag可以为0、O_CREAT或O_CREAT|O_EXCL。如果指定了O_CREAT标志,那么后面两个参数是需要的: 58 | - mode指定权限位, 59 | - value指定信号量初始值。二值信号量为1,计数信号量则往往 >1 60 | - oflag为O_CREAT时,如果信号量尚未存在,就创建,如果已存在,就打开 61 | - oflag为O_CREAT|O_EXCL时,如果信号量已存在,出错 62 | 63 | int sem_close(sem_t *sem); 64 | 返回:成功返回0,出错返回-1 65 | 66 | sem_close关闭使用`sem_open`打开的有名信号量 67 | 68 | int sem_unlink(const char *name); 69 | 返回:成功返回0,出错返回-1 70 | 71 | sem_unlink从系统中删除有名信号量 72 | 73 | 每个信号量有几个引用计数器记录当前的打开次数,sem_unlink类似于文件I/O的unlink函数:当引 74 | 用计数还是大于0时,name就能从文件系统删除,然而其信号量的析构却要等到最后一个sem_close发生时为止。 75 | 76 | int sem_wait(sem_t *sem); 77 | int sem_trywait(sem_t *sem); 78 | 返回:成功返回0,出错返回-1 79 | 80 | - sem_wait测试所指定信号量的值,如果大于0,将它减1并返回。如果等于0,调用线程就被sleep,直 81 | 到该值变为大于0,这时再将它减1,函数随后返回。 **测试并减1必须是原子**的 82 | - sem_trywait与sem_wait类似,不同之处在于,如果所指定的信号量值已经是0,调用线程不会 83 | 被sleep,函数立即返回,返回EAGAIN错误 84 | - 如果调用被某个信号中断,sem_wait可能过早地返回,返回错误为EINTR。 85 | 86 | int sem_post(sem_t *sem); 87 | int sem_getvalue(sem_t *sem, int *valp); 88 | 返回:成功返回0,出错返回-1 89 | 90 | 当一个线程使用完某个信号量时,应该调用`sem_post`,把所指定的信号量的值加1,然后唤醒正在等待 91 | 该信号量值变为正数的任意线程。 92 | 93 | - `sem_getvalue`在由`valp`指向的整数中返回所指定信号量的当前值。如果该信号量当前已上锁,那 94 | 么返回0或某个负数(该负数的绝对值表示等待该信号量解锁的线程数) 95 | 96 | ``` 97 | 98 | * 一个进程终止时,内核还对其上仍然打开着的所有有名信号量自动执行这样的信号量关闭操作(不论 99 | 是自愿终止还是非自愿终止) 100 | * 关闭一个信号量并没有将它从系统中删除。Posix有名信号量至少是随内核持续的:即使当前没有进 101 | 程打开着某个信号量,它的值仍然保持。 102 | 103 | 104 | 105 | #####示例程序 106 | 107 | 优于Posix有名信号量至少具有随内核的持续性,因此我们可以**跨多个程序**操纵它们。 108 | 109 | ```bash 110 | . 111 | ├── makefile 112 | ├── producer_consumer 113 | │   ├── makefile 114 | │   ├── producer_consumer01.c 115 | │   └── producer_consumer02.c 116 | ├── README.md 117 | ├── semcreate.c 创建有名信号量 118 | ├── semgetvalue.c 获取有名信号量的当前值 119 | ├── sempost.c 给指定有名信号量值+1 120 | ├── semunlink.c 删除一个有名信号量 121 | └── semwait.c 等待一个有名信号量,一旦其值>0,返回并-1 122 | 123 | ``` 124 | 125 | 以上semxxx.c是几个用来操纵信号量的小程序,我们的演示过程如下,演示环境为ubuntu 14.04lts 版本 126 | 127 | ```bash 128 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semcreate test 129 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semgetvalue test 130 | value = 1 131 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semwait test 132 | pid 2952 has semaphore, value = 0 133 | ^C 134 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semgetvalue test 135 | value = 0 # 仍然为0 136 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semwait test & 137 | [1] 2955 138 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semgetvalue test 139 | value = 0 # 本实现不使用负值来表示当前等待该信号量的进程/线程数 140 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semwait test & 141 | [2] 2957 142 | carl@localhost:~/demo/ipc/posix_semaphore$ ./semgetvalue test 143 | value = 0 144 | carl@localhost:~/demo/ipc/posix_semaphore$ ./sempost test 145 | pid 2955 has semaphore, value = 0 146 | value = 0 # 看起来等待着的进程优于挂出信号量的进程运行 147 | carl@localhost:~/demo/ipc/posix_semaphore$ ./sempost test 148 | pid 2957 has semaphore, value = 0 149 | value = 0 150 | ``` 151 | 152 | - producer_consumer01.c 使用Posix有名信号量,单生产者-单消费者示例 153 | 154 | 155 | #####基于内存的信号量 156 | --- 157 | 158 | 以上讲述的都是Posix有名信号量,这些信号量由一个name参数标识,它通常指代文件系 159 | 统中的某个文件。彼此无亲缘关系的不同进程需使用信号量时,通常使用有名信号量。 160 | 161 | Posix也提供基于内存的信号量,由应用程序分配信号量的内存空间,然后由系统初始化它们的值。 162 | 163 | ```cpp 164 | #include 165 | 166 | int sem_init(sem_t *sem, int shared, unsigned int value); 167 | 返回: 成功返回0,失败返回-1 168 | 169 | 基于内存的信号量由sem_init初始化 170 | 171 | - sem参数指向应用**应用程序必须分配**的sem_t变量。 172 | - shared==0,待初始化的信号量是在同一进程的各个线程间共享 173 | - shared!=0,待初始化的信号量是在不同进程间共享。该信号量必须存放在某种类 174 | 型的共享内存区中,而即将使用它的所有进程都要能访问该共享内存区。 175 | - value参数,是该信号量的初始值 176 | 177 | 注意: 178 | 179 | - 对于一个给定的信号量,必须小心保证只调用`semm_init`一次。对一个已初始化过的信号 180 | 量调用`sem_init`,结果是未定义的。 181 | - fork出来的子进程通常不共享父进程的内存空间,它是在父进程内存空间的副本上启动的. 因 182 | 此,基于内存的信号量不能在fork的父子进程间共享。但是有名信号量可以,在父进程中打开的 183 | 任何信号量仍应在子进程中打开 184 | 185 | 基于内存的信号量至少具有随进程的持续性,然而它们真正的持续性却取决于存放信号量的 186 | 内存区的类型。只要含有某个内存信号量的内存区保持有效,该信号量就一直存在。 187 | 188 | - 如果某个基于内存的信号量是由单个进程内的各个线程共享的,那么该信号量具有随进程的持 189 | 续性,当该进程终止时它也消失。 190 | - 如果某个基于内存的信号量是在不同进程间共享的,那么该信号量必须存放在共享内存区 191 | 中,因而只要该共享内存区仍然存在,该信号量也就继续存在 192 | - 服务器可以创建一个共享内存区,在该共享内存区中初始化一个Posix基于内存的信号量,然 193 | 后终止。一段时间后,一个或多个客户可打开该共享内存区,访问存放在其中的基于内存的 194 | 信号量。 195 | 196 | int sem_destroy(sem_t *sem); 197 | 返回: 成功返回0,失败返回-1 198 | 199 | 使用完一个基于内存的信号量后,调用sem_destroy销毁它 200 | 201 | ``` 202 | 203 | * producer_consumer02.c 使用Posix基于内存的信号量,单生产者-单消费者问题示例。 204 | 205 | 206 | #####信号量限制 207 | --- 208 | 209 | - SEM_NSEMS_MAX 一个进程可同时打开着的最大信号量数 210 | - SEM_VALUE_MAX 一个信号量的最大值 211 | - get_sys_conf.c 通过sysconf获取当前系统的以上两个值 212 | -------------------------------------------------------------------------------- /thrift/01/gen-cpp/Serv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.1) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef Serv_H 8 | #define Serv_H 9 | 10 | #include 11 | #include "student_types.h" 12 | 13 | 14 | 15 | class ServIf { 16 | public: 17 | virtual ~ServIf() {} 18 | virtual void put(const Student& s) = 0; 19 | }; 20 | 21 | class ServIfFactory { 22 | public: 23 | typedef ServIf Handler; 24 | 25 | virtual ~ServIfFactory() {} 26 | 27 | virtual ServIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; 28 | virtual void releaseHandler(ServIf* /* handler */) = 0; 29 | }; 30 | 31 | class ServIfSingletonFactory : virtual public ServIfFactory { 32 | public: 33 | ServIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} 34 | virtual ~ServIfSingletonFactory() {} 35 | 36 | virtual ServIf* getHandler(const ::apache::thrift::TConnectionInfo&) { 37 | return iface_.get(); 38 | } 39 | virtual void releaseHandler(ServIf* /* handler */) {} 40 | 41 | protected: 42 | boost::shared_ptr iface_; 43 | }; 44 | 45 | class ServNull : virtual public ServIf { 46 | public: 47 | virtual ~ServNull() {} 48 | void put(const Student& /* s */) { 49 | return; 50 | } 51 | }; 52 | 53 | typedef struct _Serv_put_args__isset { 54 | _Serv_put_args__isset() : s(false) {} 55 | bool s; 56 | } _Serv_put_args__isset; 57 | 58 | class Serv_put_args { 59 | public: 60 | 61 | Serv_put_args() { 62 | } 63 | 64 | virtual ~Serv_put_args() throw() {} 65 | 66 | Student s; 67 | 68 | _Serv_put_args__isset __isset; 69 | 70 | void __set_s(const Student& val) { 71 | s = val; 72 | } 73 | 74 | bool operator == (const Serv_put_args & rhs) const 75 | { 76 | if (!(s == rhs.s)) 77 | return false; 78 | return true; 79 | } 80 | bool operator != (const Serv_put_args &rhs) const { 81 | return !(*this == rhs); 82 | } 83 | 84 | bool operator < (const Serv_put_args & ) const; 85 | 86 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 87 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 88 | 89 | }; 90 | 91 | 92 | class Serv_put_pargs { 93 | public: 94 | 95 | 96 | virtual ~Serv_put_pargs() throw() {} 97 | 98 | const Student* s; 99 | 100 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 101 | 102 | }; 103 | 104 | 105 | class Serv_put_result { 106 | public: 107 | 108 | Serv_put_result() { 109 | } 110 | 111 | virtual ~Serv_put_result() throw() {} 112 | 113 | 114 | bool operator == (const Serv_put_result & /* rhs */) const 115 | { 116 | return true; 117 | } 118 | bool operator != (const Serv_put_result &rhs) const { 119 | return !(*this == rhs); 120 | } 121 | 122 | bool operator < (const Serv_put_result & ) const; 123 | 124 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 125 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 126 | 127 | }; 128 | 129 | 130 | class Serv_put_presult { 131 | public: 132 | 133 | 134 | virtual ~Serv_put_presult() throw() {} 135 | 136 | 137 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 138 | 139 | }; 140 | 141 | class ServClient : virtual public ServIf { 142 | public: 143 | ServClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : 144 | piprot_(prot), 145 | poprot_(prot) { 146 | iprot_ = prot.get(); 147 | oprot_ = prot.get(); 148 | } 149 | ServClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : 150 | piprot_(iprot), 151 | poprot_(oprot) { 152 | iprot_ = iprot.get(); 153 | oprot_ = oprot.get(); 154 | } 155 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { 156 | return piprot_; 157 | } 158 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { 159 | return poprot_; 160 | } 161 | void put(const Student& s); 162 | void send_put(const Student& s); 163 | void recv_put(); 164 | protected: 165 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; 166 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; 167 | ::apache::thrift::protocol::TProtocol* iprot_; 168 | ::apache::thrift::protocol::TProtocol* oprot_; 169 | }; 170 | 171 | class ServProcessor : public ::apache::thrift::TDispatchProcessor { 172 | protected: 173 | boost::shared_ptr iface_; 174 | virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, void* callContext); 175 | private: 176 | typedef void (ServProcessor::*ProcessFunction)(int32_t, ::apache::thrift::protocol::TProtocol*, ::apache::thrift::protocol::TProtocol*, void*); 177 | typedef std::map ProcessMap; 178 | ProcessMap processMap_; 179 | void process_put(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); 180 | public: 181 | ServProcessor(boost::shared_ptr iface) : 182 | iface_(iface) { 183 | processMap_["put"] = &ServProcessor::process_put; 184 | } 185 | 186 | virtual ~ServProcessor() {} 187 | }; 188 | 189 | class ServProcessorFactory : public ::apache::thrift::TProcessorFactory { 190 | public: 191 | ServProcessorFactory(const ::boost::shared_ptr< ServIfFactory >& handlerFactory) : 192 | handlerFactory_(handlerFactory) {} 193 | 194 | ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); 195 | 196 | protected: 197 | ::boost::shared_ptr< ServIfFactory > handlerFactory_; 198 | }; 199 | 200 | class ServMultiface : virtual public ServIf { 201 | public: 202 | ServMultiface(std::vector >& ifaces) : ifaces_(ifaces) { 203 | } 204 | virtual ~ServMultiface() {} 205 | protected: 206 | std::vector > ifaces_; 207 | ServMultiface() {} 208 | void add(boost::shared_ptr iface) { 209 | ifaces_.push_back(iface); 210 | } 211 | public: 212 | void put(const Student& s) { 213 | size_t sz = ifaces_.size(); 214 | size_t i = 0; 215 | for (; i < (sz - 1); ++i) { 216 | ifaces_[i]->put(s); 217 | } 218 | ifaces_[i]->put(s); 219 | } 220 | 221 | }; 222 | 223 | 224 | 225 | #endif 226 | --------------------------------------------------------------------------------