PCSC那事兒(二十九--PCSCD)


 

繞來繞去,回到 pcscdaemon.c

346                 else

347                 {

348                         if (HotPlug)

349                         {

350                                  Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");

351                                 Log1(PCSC_LOG_CRITICAL, "Hotplug failed");

352                                 return EXIT_FAILURE;

353                         }

354

355                         Log1(PCSC_LOG_CRITICAL,

356                                 "file " PCSCLITE_PUBSHM_FILE " already exists.");

357                         Log1(PCSC_LOG_CRITICAL,

358                                 "Maybe another pcscd is running?");

359                         Log1(PCSC_LOG_CRITICAL,

360                                 "I can't read process pid from " PCSCLITE_RUN_PID);

361                         Log1(PCSC_LOG_CRITICAL,

362                                 "Remove " PCSCLITE_PUBSHM_FILE " and " PCSCLITE_CSOCK_NAME);

363                         Log1(PCSC_LOG_CRITICAL,

364                                 "if pcscd is not running to clear this message.");

365                         return EXIT_FAILURE;

366                  }

346~366 行,如果從 PCSCLITE_RUN_PID 無法正確讀取 pid, 則打印一大堆錯誤。

367         }

368         else

369                 if (HotPlug)

370                 {

371                         Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");

372                          return EXIT_FAILURE;

373                 }

369~373 行,如果共享內存文件不存在,則命令行有 HotPlug 則錯誤直接退出。

當然也可以采用不退出,繼續創建必要的文件,並啟動 pcscd. 但是這里采用了前者的方法。 

374

375         /*

376          * If this is set to one the user has asked it not to fork

377          */

378         if (!setToForeground)

379         {

380                 if (SYS_Daemon(0, 0))

381                         Log2(PCSC_LOG_CRITICAL, "SYS_Daemon() failed: %s",

382                                 strerror(errno));

383         }

 

374~383 行,如果不是前台運行模式,也就是采用后台運行模式,則采用 daemon 方式啟動 pcscd.

384

385         /*

386          * cleanly remove /var/run/pcscd/files when exiting

387          */

388         (void)signal(SIGQUIT, signal_trap);

389         (void)signal(SIGTERM, signal_trap);

390          (void)signal(SIGINT, signal_trap);

391         (void)signal(SIGHUP, signal_trap);

392

 

384~392 行,系統信號處理。

SIGQUIT 可以從控制終端發 SIGQUIT 給進程, 請求進程 dump core

SIGTERM kill 命令引發的信號。

SIGINT 按下 ctrl+c 引發的信號。

SIGHUP 在用戶終端連接 ( 正常或非正常 ) 結束時發出,通常是在終端的控制進程結束時,

通知同一 session 內的各個作業,這時它們與控制終端不再關聯。

 

OK. 關於信號的內容很多很多。適可而止。

上面重定向了這 4 個信號。采用統一個處理函數, 整齊划一,泯滅個性。 這個處理函數是 signal_trap.

也在 pcscdaemon.c 中實現。

581 static void signal_trap(/*@unused@*/ int sig)

582 {

583         (void)sig;

584

585         /* the signal handler is called several times for the same Ctrl-C */

586         if (AraKiri == FALSE)

587         {

588                 Log1(PCSC_LOG_INFO, "Preparing for suicide");

589                 AraKiri = TRUE;

590

591                 /* if still in the init/loading phase the AraKiri will not be

592                  * seen by the main event loop

593                  */

594                 if (Init)

595                 {

596                         Log1(PCSC_LOG_INFO, "Suicide during init");

597                         at_exit();

598                 }

599         }

600 }

 

 

Init 是個特殊標志,代表 pcscd 是否處於初始化階段。

main 函數的

517         Init = FALSE;

之后,就代表過了初始化階段。僅僅而已。

 

這個處理過程,僅僅變動了一個標志 AraKiri. 這個標志的目的,等吧 ... 等以后解釋。

不能等,那么就看看 175 頁吧。答應了,就一定會說到做到的。

 

at_exit 也實現在同一個文件中,

535 static void at_exit(void)

536 {

537         Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);

538

539         clean_temp_files();

540

541         SYS_Exit(ExitValue);

542 }

535~542 行,清除上面提到的4組臨時文件,進程退出 .

ExitValue 有兩個自解釋的枚舉值:

EXIT_SUCCESS

EXIT_FAILURE

 

 

通過上面的分析知道,共享文件不存在的情況下,則需要創建包括共享文件在內的上面

提到的臨時文件。包括

PCSCLITE_RUN_PID 文件 (/var/run/pcscd/pcscd.pid)

PCSCLITE_EVENTS_DIR 目錄 (/var/run/pcscd/pcscd.events)

 

下面創建存放 PCSCLITE_RUN_PID 文件的目錄

393         /*

394          * If PCSCLITE_IPC_DIR does not exist then create it

395          */

396         rv = SYS_Stat(PCSCLITE_IPC_DIR, &fStatBuf);

397         if (rv < 0)

398         {

399                 int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;

400

401                 rv = SYS_Mkdir(PCSCLITE_IPC_DIR, mode);

402                 if (rv != 0)

403                 {

404                         Log2(PCSC_LOG_CRITICAL,

405                                 "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));

406                         return EXIT_FAILURE;

407                 }

408

409                 /* set mode so that the directory is world readable and

410                  * executable even is umask is restrictive

411                  * The directory containes files used by libpcsclite */

412                 (void)SYS_Chmod(PCSCLITE_IPC_DIR, mode);

413         }

414

415         /*

416          * Record our pid to make it easier

417          * to kill the correct pcscd

418          */

419         {

420                 int f;

421                 int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

422

423                 if ((f = SYS_OpenFile(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode)) != -1)

424                 {

425                         char pid[PID_ASCII_SIZE];

426

427                          (void)snprintf(pid, sizeof(pid), "%u/n", (unsigned) getpid());

428                         (void)SYS_WriteFile(f, pid, strlen(pid));

429                         (void)SYS_CloseFile(f);

430

431                         /* set mode so that the file is world readable even is umask is

432                          * restrictive

433                          * The file is used by libpcsclite */

434                         (void)SYS_Chmod(PCSCLITE_RUN_PID, mode);

435                 }

436                 else

437                         Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",

438                                 strerror(errno));

439         }

414~439 行,創建 PCSCLITE_RUN_PID 文件,並往文件中寫入當前進程的 pid.

這樣其它的進程,包括后續啟動的 pcscd 可以方便地得到這個 pcscd 的進程 pid.

 

440

441         /*

442          * If PCSCLITE_EVENTS does not exist then create it

443          */

444         rv = SYS_Stat(PCSCLITE_EVENTS_DIR, &fStatBuf);

445          if (rv < 0)

446         {

447                 /* 1733 : world writable + sticky bit */

448                 int mode = S_IRWXU | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH | S_ISVTX;

449

450                 rv = SYS_Mkdir(PCSCLITE_EVENTS_DIR, mode);

451                  if (rv != 0)

452                 {

453                         Log2(PCSC_LOG_CRITICAL,

454                                 "cannot create " PCSCLITE_EVENTS_DIR ": %s", strerror(errno));

455                         return EXIT_FAILURE;

456                 }

457                 (void)SYS_Chmod(PCSCLITE_EVENTS_DIR, mode);

458         }

440~458 行,創建 PCSCLITE_EVENTS_DIR 目錄,方便 APPLICATION pcscd 的事件通訊。

 

459

460         /* cleanly remove /var/run/pcscd/pcsc.* files when exiting */

461          if (atexit(at_exit))

462                 Log2(PCSC_LOG_CRITICAL, "atexit() failed: %s", strerror(errno));

463

atexit 設置程序正常結束前調用的函數。

當程序通過 exit 或從 main 中返回,參數 function 所指定的函數會先被調用,

然后真正由 exit 結束程序。

也就是說,如果程序正常退出,則調用 at_exit. 很像析構吧。

at_exit 在上面解釋了。移除 /var/run/pcscd/ 下, pcsc 開頭的 3 個文件和一個目錄。

3 個文件是:

/var/run/pcscd/pcscd.pub

/var/run/pcscd/pcscd.comm

/var/run/pcscd/pcscd.pid

1 個目錄是:

/var/run/pcscd/pcscd.events

 

 

繼續,繼續。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com